LintCode Q 178 - Graph Valid Tree
Given n nodes labeled from 0 to n - 1 and a list of undirected edges (each edge is a pair of nodes), write a function to check whether these edges make up a valid tree.
Example 1:Input: n = 5 edges = [[0, 1], [0, 2], [0, 3], [1, 4]] ; Output: true.
Example 2:Input: n = 5 edges = [[0, 1], [1, 2], [2, 3], [1, 3], [1, 4]] ; Output: false.
Notice: You can assume that no duplicate edges will appear in edges. Since all edges are undirected, [0, 1] is the same as [1, 0] and thus will not appear together in edges.
Solution
An undirected graph is tree if it has following properties.
- There is no cycle.
- The graph is connected.
How to check if a graph satisfies the above two properties?
- If there are N nodes and N-1 edges, then the graph has no cycle. That is
edges = n - 1
. - There is no island in the graph, if and only if we can visit every node in the graph from any arbitrary node in the graph.
Solution 1 : BFS
Code:
public boolean validTree(int n, int[][] edges) {
if (n == 0) return false;
if (edges.length != n - 1) return false;
Map<Integer, Set<Integer>> graph = new HashMap<>();
// build the graph
for (int i = 0; i < n; i++)
graph.put(i, new HashSet<>());
for (int[] edge: edges) {
graph.get(edge[0]).add(edge[1]);
graph.get(edge[1]).add(edge[0]);
}
Queue<Integer> que = new PriorityQueue<>();
Set<Integer> visited = new HashSet<>();
que.offer(0); visited.add(0);
while (!que.isEmpty()) {
int curr = que.poll();
for (int next: graph.get(curr)) {
if (visited.contains(next)) continue;
que.offer(next);
visited.add(next);
}
}
return vistied.size() == n;
}
Solution 2 : Disjoint Set / Union Find Set
- Build the union, if I am trying to union an existing edge, then return false;
- Check if there is only one union in the graph.
Another way:
- Add a count field in the UnionFindSet, denoting the number of different unions.
- check if the
count
for the given graph equals1
.
Code:
class UnionFindSet {
int[] parent;
int[] rank;
public UnionFindSet(int size) {
parent = new int[size]; rank = new int[size];
for (int i = 0; i < size; i++)
parent[i] = i;
}
public int Find (int x) {
if (x != parent[x])
parent[x] = Find(parent[x]);
return parent[x];
}
public void Union (int x, int y) {
int px = Find(x), py = Find(y);
if (rank(px) > rank(py)) parent[py] = px;
if (rank(py) > rank(px)) parent[px] = py;
else {
parent[py] = px;
rank[px]++;
}
}
}
public boolean validTree(int n, int[][] edges) {
if (n == 0) return false;
if (edges.length != n - 1) return false;
UnionFindSet ufs = new UnionFindSet();
for (int[] edge: edges) {
if (ufs.find(edge[0]) == ufs.find(edge[1])) return false;
ufs.union(edge[0], edge[1]);
}
for (int i = 1; i < n; i++) {
if (ufs.find(i - 1) != ufs.find(i)) return false;
}
return true;
}