-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathsolution.py
106 lines (85 loc) · 2.59 KB
/
solution.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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
"""
Approach: Strongly Connected Components, DFS, DP on DAG
Time Complexity: O(N + M + Q)
Space Complexity: O(N + M + Q)
"""
from sys import setrecursionlimit
setrecursionlimit(10**6)
def strongly_connected_components(graph):
N = len(graph)
rev_graph = [[] for _ in range(N)]
for u in range(N):
for v in graph[u]:
rev_graph[v].append(u)
stack, components = [], []
def dfs(u, visited):
visited[u] = True
for v in graph[u]:
if not visited[v]:
dfs(v, visited)
stack.append(u)
def dfs_rev(u, visited, component):
visited[u] = True
for v in rev_graph[u]:
if not visited[v]:
dfs_rev(v, visited, component)
component.append(u)
visited = [False] * N
for u in range(N):
if not visited[u]:
dfs(u, visited)
visited = [False] * N
for u in stack[::-1]:
if not visited[u]:
component = []
dfs_rev(u, visited, component)
components.append(component)
return components
def maximum_reachable_node(graph):
scc = strongly_connected_components(graph)
N = len(graph)
comp_mappping = [0] * N
for i, comp in enumerate(scc):
for u in comp:
comp_mappping[u] = i
induced_graph = [[] for _ in range(len(scc))]
for u in range(N):
for v in graph[u]:
if comp_mappping[u] != comp_mappping[v]:
induced_graph[comp_mappping[u]].append(comp_mappping[v])
for i in range(len(scc)):
induced_graph[i] = list(set(induced_graph[i]))
visited = [False] * len(scc)
best_path_size = [0] * len(scc)
def dfs(u):
visited[u] = True
best = 0
for v in induced_graph[u]:
if not visited[v]:
best = max(best, dfs(v))
else:
best = max(best, best_path_size[v])
best_path_size[u] = best+len(scc[u])
return best_path_size[u]
for u in range(len(scc)):
if not visited[u]:
dfs(u)
result = [0] * N
for u in range(N):
result[u] = best_path_size[comp_mappping[u]]
return result
def main():
N, M = map(int, input().split())
graph = [[] for _ in range(N)]
for _ in range(M):
u, v = map(int, input().split())
graph[u - 1].append(v - 1)
best_path_size = maximum_reachable_node(graph)
Q = int(input())
result = []
for _ in range(Q):
C = int(input())-1
result.append(str(best_path_size[C]))
return result
if __name__ == '__main__':
print(*main(), sep='\n')