-
Notifications
You must be signed in to change notification settings - Fork 8
Expand file tree
/
Copy pathscc.py
More file actions
62 lines (60 loc) · 1.76 KB
/
scc.py
File metadata and controls
62 lines (60 loc) · 1.76 KB
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
def scc(N, edges):
M = len(edges)
start = [0] * (N + 1)
elist = [0] * M
for e in edges:
start[e[0] + 1] += 1
for i in range(1, N + 1):
start[i] += start[i - 1]
counter = start[:]
for e in edges:
elist[counter[e[0]]] = e[1]
counter[e[0]] += 1
visited = []
low = [0] * N
Ord = [-1] * N
ids = [0] * N
NG = [0, 0]
def dfs(v):
stack = [(v, -1, 0), (v, -1, 1)]
while stack:
v, bef, t = stack.pop()
if t:
if bef != -1 and Ord[v] != -1:
low[bef] = min(low[bef], Ord[v])
stack.pop()
continue
low[v] = NG[0]
Ord[v] = NG[0]
NG[0] += 1
visited.append(v)
for i in range(start[v], start[v + 1]):
to = elist[i]
if Ord[to] == -1:
stack.append((to, v, 0))
stack.append((to, v, 1))
else:
low[v] = min(low[v], Ord[to])
else:
if low[v] == Ord[v]:
while True:
u = visited.pop()
Ord[u] = N
ids[u] = NG[1]
if u == v:
break
NG[1] += 1
low[bef] = min(low[bef], low[v])
for i in range(N):
if Ord[i] == -1:
dfs(i)
for i in range(N):
ids[i] = NG[1] - 1 - ids[i]
group_num = NG[1]
counts = [0] * group_num
for x in ids:
counts[x] += 1
groups = [[] for i in range(group_num)]
for i in range(N):
groups[ids[i]].append(i)
return groups