-
Notifications
You must be signed in to change notification settings - Fork 2
/
strongConnectivity.py
129 lines (106 loc) · 3.03 KB
/
strongConnectivity.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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# -*- coding: utf-8 -*-
"""
S4 - 2019-02
Strong Connectivity
"""
from algopy import graph, stack
#------------------------------------------------------------------------------
# tools
def reverseGraph(G):
G_1 = graph.Graph(G.order, True)
for s in range(G.order):
for adj in G.adjlists[s]:
G_1.addedge(adj, s)
return G_1
def from_scc2sccList(comp, nb):
c = []
for i in range(nb):
c.append([])
for i in range(len(comp)):
c[comp[i]-1].append(i)
return c
def from_sccList2scc(sccList, n):
k = len(sccList)
scc = [-1] * n
for i in range(k):
for s in sccList[i]:
scc[s] = i
return k, scc
#------------------------------------------------------------------------------
# 2.1 naive
def __dfs(G, s, M, mark = True):
M[s] = mark
for adj in G.adjlists[s]:
if not M[adj]:
__dfs(G, adj, M, mark)
def simpleDFS(G, s):
M = [False]*G.order
__dfs(G, s, M)
return M
def naiveAlgo(G):
G_1 = reverseGraph(G)
comp = [0]*G.order
no = 0
for x in range(G.order):
if comp[x] == 0:
plus = simpleDFS(G, x)
minus = simpleDFS(G_1, x)
no += 1
for y in range(G.order):
if plus[y] and minus[y]:
comp[y] = no
return (no, comp)
#------------------------------------------------------------------------------
# 2.2 Kosaraju
def __dfsPost(G, s, M, post):
M[s] = True
for adj in G.adjlists[s]:
if not M[adj]:
__dfsPost(G, adj, M, post)
post.push(s)
def Kosaraju(G):
post = stack.Stack()
M = [False]*G.order
for s in range(G.order):
if not M[s]:
__dfsPost(G, s, M, post)
G_1 = reverseGraph(G)
comp = [0]*G.order
no = 0
while not post.isEmpty():
s = post.pop()
if comp[s] == 0:
no += 1
__dfs(G_1, s, comp, no)
return (no, comp)
#------------------------------------------------------------------------------
# 2.2 Tarjan
def __Tarjan(G, x, pref, cpt, cfc, nocfc, vertexStack):
cpt += 1
pref[x] = cpt
return_x = pref[x]
vertexStack.push(x)
for y in G.adjlists[x]:
if pref[y] == 0:
(return_y, cpt, nocfc) = __Tarjan(G, y, pref, cpt, cfc, nocfc, vertexStack)
return_x = min(return_x, return_y)
else:
return_x = min(return_x, pref[y])
if return_x == pref[x]:
nocfc += 1
y = -4
while y != x:
y = vertexStack.pop()
cfc[y] = nocfc
pref[y] = 4 * G.order
return (return_x, cpt, nocfc)
def Tarjan(G):
pref = [0]*G.order
cpt = 0
vertexStack = stack.Stack()
k = 0
cfc = [0]*G.order
for s in range(G.order):
if pref[s] == 0:
(_, cpt, k) = __Tarjan(G, s, pref, cpt, cfc, k, vertexStack)
return (k, cfc )