Graph Valid Tree
Problem
An undirected graph has n nodes (numbered 0 to n-1) and m edges. Print true if the graph is a tree: it is connected and has no cycle. Input: the first line is n and m, then m lines with the two ends of each edge.
Constraints
- 1 <= n <= 10^4
- 0 <= m <= 2 * 10^4
Examples
Input
3 2 0 1 1 2
Output
true
Input
3 3 0 1 1 2 2 0
Output
false
Solutions
A tree has n - 1 edges and no cycle. After the edge count check, union-find joins the two ends of every edge. If both ends are already in one group, the edge closes a cycle. With n - 1 edges and no cycle, the graph is also connected.
/*
* Problem : Is it a tree?
* Input : n, m and the edges.
* Output : true or false.
* Approach: Union-find
* Time : O(n a(n))
* Space : O(n)
* Java : 8 or newer.
*/
import java.util.Scanner;
public class Main {
// Step 4: Find the leader of the group of x. Path halving keeps the paths short.
static int find(int[] parent, int x) {
while (parent[x] != x) {
parent[x] = parent[parent[x]];
x = parent[x];
}
return x;
}
// This method solves the task. It receives the input and returns the answer.
static boolean solve(String[] lines) {
String[] first = lines[0].split(" ");
int n = Integer.parseInt(first[0]);
int m = Integer.parseInt(first[1]);
// Step 1: A tree with n nodes has exactly n - 1 edges. Any other count is wrong at once.
if (m != n - 1) {
return false;
}
// Step 2: Union-find: parent[x] points towards the leader of the group of x.
int[] parent = new int[n];
for (int i = 0; i < n; i++) {
parent[i] = i;
}
for (int i = 1; i <= m; i++) {
String[] edge = lines[i].split(" ");
int u = find(parent, Integer.parseInt(edge[0]));
int v = find(parent, Integer.parseInt(edge[1]));
// Step 3: Both ends already in one group: this edge makes a cycle.
if (u == v) {
return false;
}
parent[u] = v;
}
return true;
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
java.util.List<String> all = new java.util.ArrayList<>();
while (scanner.hasNextLine()) {
String line = scanner.nextLine().trim();
if (!line.isEmpty()) {
all.add(line);
}
}
String[] lines = all.toArray(new String[0]);
System.out.println(solve(lines));
}
}
Hints (2)
- How many edges has a tree?
- Why is connected implied?