Source code for titan_pylib.graph.get_scc_graph
1from titan_pylib.others.antirec import antirec
2
3
[docs]
4def get_scc_graph(G: list[list[int]]):
5 """
6 scc, 頂点を縮約した隣接リスト, もとの頂点->新たなグラフの頂点
7 """
8 n = len(G)
9 stack = [0] * n
10 ptr = 0
11 lowlink = [-1] * n
12 order = [-1] * n
13 ids = [0] * n
14 cur_time = 0
15 group_cnt = 0
16
17 @antirec
18 def dfs(v: int):
19 nonlocal cur_time, ptr
20 order[v] = cur_time
21 lowlink[v] = cur_time
22 cur_time += 1
23 stack[ptr] = v
24 ptr += 1
25 for x in G[v]:
26 if order[x] == -1:
27 yield dfs(x)
28 lowlink[v] = min(lowlink[v], lowlink[x])
29 else:
30 lowlink[v] = min(lowlink[v], order[x])
31 if lowlink[v] == order[v]:
32 nonlocal group_cnt
33 while True:
34 u = stack[ptr - 1]
35 ptr -= 1
36 order[u] = n
37 ids[u] = group_cnt
38 if u == v:
39 break
40 group_cnt += 1
41 yield
42
43 for v in range(n):
44 if order[v] == -1:
45 dfs(v)
46 groups = [[] for _ in range(group_cnt)]
47 for v in range(n):
48 groups[group_cnt - 1 - ids[v]].append(v)
49
50 F = [set() for _ in range(max(ids) + 1)]
51 for v in range(n):
52 for x in G[v]:
53 if ids[v] != ids[x]:
54 F[ids[v]].add(ids[x])
55 F = [list(f) for f in F]
56 return groups, F, ids