-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathStronglyConnectedComponent.py
94 lines (83 loc) · 2.14 KB
/
StronglyConnectedComponent.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
# THIS IS WRONG. WASTED A DAY ON THIS!
# given a digraph:
# determine whether two vertices are strongly connected
# determine number of strongly connected components
#
# DG = Digraph(13)
# DG.addEdge(0, 5)
# ...
# scc = SCC(DG)
# scc.stronglyConnected(0, 3) => True
# scc.number() => 5
#
from GraphLib import Digraph
class SCC(object):
def __init__(self, G):
self._G = G
self._marked = [False for _ in range(G.V())]
# initialize each id to its vertex number (only connected to itself)
self._id = [i for i in range(G.V())]
for v in range(G.V()):
self._count = v
self._cycle = []
if not self._marked[v]:
self._dfs(G, v)
def _dfs(self, G, v):
self._marked[v] = True
if self._outdegree(v) == 0:
# vertex has no out edges
return
self._cycle.append(v)
for w in G.adj(v):
if not self._marked[w]:
self._dfs(G, w)
elif w in self._cycle:
# cycle detected
# if cycle begins at index 0, then assign each vertex the min id of any vertex in cycle
# otherwise, each vertex in cycle is assigned the id of w (the marked vertex)
print self._cycle, 'w', w
index = self._cycle.index(w)
cycle = self._cycle[index:]
m = min(cycle)
if index == 0:
for i in cycle:
self._id[i] = self._id[m]
else:
for i in cycle:
# id[w] has already been assigned because w is in the cycle
self._id[i] = self._id[w]
def _outdegree(self, v):
"return out degree of vertex v"
return len(self._G.adj(v))
def _indegree(self, v):
"return True if vertex has an input edge from some other vertex"
for e in range(self._G.V()):
if e != v and v in self._G.adj(e).values():
return 1
return 0
def stronglyConnected(self, v, w):
return self._id[v] == self._id[w]
def number(self):
return len(set(self._id))
DG = Digraph(13)
DG.addEdge(4, 2)
DG.addEdge(2, 3)
DG.addEdge(3, 2)
DG.addEdge(6, 0)
DG.addEdge(0, 1)
DG.addEdge(2, 0)
DG.addEdge(11, 12)
DG.addEdge(12, 9)
DG.addEdge(9, 10)
DG.addEdge(9, 11)
DG.addEdge(10, 12)
DG.addEdge(11, 4)
DG.addEdge(4, 3)
DG.addEdge(3, 5)
DG.addEdge(6, 8)
DG.addEdge(8, 6)
DG.addEdge(5, 4)
DG.addEdge(0, 5)
DG.addEdge(6, 4)
DG.addEdge(6, 9)
DG.addEdge(7, 6)