Skip to content

Commit aae3d08

Browse files
authored
Create count-subtrees-with-max-distance-between-cities.py
1 parent 75b9cc9 commit aae3d08

File tree

1 file changed

+103
-0
lines changed

1 file changed

+103
-0
lines changed
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
# Time: O(n^5)
2+
# Space: O(n^3)
3+
4+
import collections
5+
6+
7+
class Solution(object):
8+
def countSubgraphsForEachDiameter(self, n, edges):
9+
"""
10+
:type n: int
11+
:type edges: List[List[int]]
12+
:rtype: List[int]
13+
"""
14+
def dfs(n, adj, curr, parent, lookup, count, dp):
15+
children = []
16+
for child in adj[curr]:
17+
if child == parent or lookup[child]:
18+
continue
19+
dfs(n, adj, child, curr, lookup, count, dp)
20+
children.append(child)
21+
for child in children:
22+
new_dp_curr = [row[:] for row in dp[curr]];
23+
for d in xrange(count[child]):
24+
for max_d in xrange(count[child]):
25+
new_dp_curr[d+1][max(max_d, d+1)] += dp[child][d][max_d]
26+
for curr_d in xrange(count[curr]):
27+
for curr_max_d in xrange(count[curr]):
28+
if not dp[curr][curr_d][curr_max_d]:
29+
continue
30+
for child_d in xrange(count[child]):
31+
for child_max_d in xrange(count[child]):
32+
max_d = max(curr_max_d, child_max_d, curr_d+child_d+1)
33+
if max_d < len(new_dp_curr[max(curr_d, child_d+1)]):
34+
new_dp_curr[max(curr_d, child_d+1)][max_d] += dp[curr][curr_d][curr_max_d]*dp[child][child_d][child_max_d]
35+
dp[curr] = new_dp_curr
36+
count[curr] += count[child]
37+
dp[curr][0][0] = 1
38+
39+
adj = collections.defaultdict(list)
40+
for u, v in edges:
41+
u -= 1
42+
v -= 1
43+
adj[u].append(v)
44+
adj[v].append(u)
45+
lookup, result = [0 for _ in xrange(n)], [0 for _ in xrange(n-1)]
46+
for i in xrange(n):
47+
dp = [[[0]*n for _ in xrange(n)] for _ in xrange(n)]
48+
count = [1]*n
49+
dfs(n, adj, i, -1, lookup, count, dp)
50+
lookup[i] = 1
51+
for d in xrange(1, n):
52+
for max_d in xrange(1, n):
53+
result[max_d-1] += dp[i][d][max_d]
54+
return result
55+
56+
57+
# Time: O(n * 2^n)
58+
# Space: O(n)
59+
import collections
60+
61+
62+
class Solution2(object):
63+
def countSubgraphsForEachDiameter(self, n, edges):
64+
"""
65+
:type n: int
66+
:type edges: List[List[int]]
67+
:rtype: List[int]
68+
"""
69+
def bfs(adj, node_set, start):
70+
q = collections.deque([(start, 0)])
71+
lookup = {start}
72+
u, d = None, None
73+
while q:
74+
u, d = q.popleft()
75+
for v in adj[u]:
76+
if v not in node_set or v in lookup:
77+
continue
78+
lookup.add(v)
79+
q.append((v, d+1))
80+
return len(lookup) == len(node_set), u, d
81+
82+
def max_distance(n, edges, adj, mask):
83+
node_set = set()
84+
base = 1
85+
for i in xrange(n):
86+
if mask & base:
87+
node_set.add(i)
88+
base <<= 1
89+
is_valid, farthest, _ = bfs(adj, node_set, next(iter(node_set), None))
90+
return bfs(adj, node_set, farthest)[-1] if is_valid else 0
91+
92+
adj = collections.defaultdict(list)
93+
for u, v in edges:
94+
u -= 1
95+
v -= 1
96+
adj[u].append(v)
97+
adj[v].append(u)
98+
result = [0 for _ in xrange(n-1)]
99+
for mask in xrange(1, 2**n):
100+
d = max_distance(n, edges, adj, mask)
101+
if d-1 >= 0:
102+
result[d-1] += 1
103+
return result

0 commit comments

Comments
 (0)