-
Notifications
You must be signed in to change notification settings - Fork 2.3k
/
0261-graph-valid-tree.py
73 lines (59 loc) · 2.03 KB
/
0261-graph-valid-tree.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# Problem is free on Lintcode
class Solution:
"""
@param n: An integer
@param edges: a list of undirected edges
@return: true if it's a valid tree, or false
"""
def validTree(self, n, edges):
if not n:
return True
adj = {i: [] for i in range(n)}
for n1, n2 in edges:
adj[n1].append(n2)
adj[n2].append(n1)
visit = set()
def dfs(i, prev):
if i in visit:
return False
visit.add(i)
for j in adj[i]:
if j == prev:
continue
if not dfs(j, i):
return False
return True
return dfs(0, -1) and n == len(visit)
# alternative solution via DSU O(ElogV) time complexity and
# save some space as we don't recreate graph\tree into adjacency list prior dfs and loop over the edge list directly
class Solution:
"""
@param n: An integer
@param edges: a list of undirected edges
@return: true if it's a valid tree, or false
"""
def __find(self, n: int) -> int:
while n != self.parents.get(n, n):
n = self.parents.get(n, n)
return n
def __connect(self, n: int, m: int) -> None:
pn = self.__find(n)
pm = self.__find(m)
if pn == pm:
return
if self.heights.get(pn, 1) > self.heights.get(pm, 1):
self.parents[pn] = pm
else:
self.parents[pm] = pn
self.heights[pm] = self.heights.get(pn, 1) + 1
self.components -= 1
def valid_tree(self, n: int, edges: List[List[int]]) -> bool:
# init here as not sure that ctor will be re-invoked in different tests
self.parents = {}
self.heights = {}
self.components = n
for e1, e2 in edges:
if self.__find(e1) == self.__find(e2): # 'redundant' edge
return False
self.__connect(e1, e2)
return self.components == 1 # forest contains one tree