By definition, we know that “tree” is a acyclic, connected graph. Therefore, in this problem, we only need to check if it’s acyclic and connected.
The basic idea is, if there’s a node that we’ve visited and it’s not the parent of node, then there is cycle. We can also use Union Find to detect cycles in undirected graphs.
defvalidTree(self, n, edges): """ :type n: int :type edges: List[List[int]] :rtype: bool """ # check cycle and connected from collections import defaultdict graph = defaultdict(list) for a, b in edges: graph[a].append(b) graph[b].append(a) visit = set()
defDFS(node, parent): if node in visit: returnFalse visit.add(node) for neighbor in graph[node]: if neighbor notin visit: child = DFS(neighbor, node) ifnot child: returnFalse else: if neighbor != parent: returnFalse returnTrue cycle = DFS(0, -1) return cycle and len(visit) == n
There is also another way to check cycles – using Union Find. The idea is, for each edge (u,v), u and v cannot be in the same set. This is useful if the given input is edges instead of nodes because you don’t need to construct the nodes again.
defvalidTree(self, n, edges): # write your code here if n == 1: returnTrue deffind(node): if graph[node] == node: return node root = find(graph[node]) graph[node] = root # path compression return root defunion(root, node): graph[graph[node]] = graph[root] graph = list(range(n)) visit = set() for a, b in edges: visit.add(a) visit.add(b) if find(a) == find(b): returnFalse union(a, b) return len(visit) == n