Skip to content

Commit e9c28af

Browse files
rubalsxnghRubal Singh
and
Rubal Singh
authored
Add Kosaraju algorithm (#910)
* added kosaraju's algorithm under /algorithms/graph * added test case for /algorithms/graph/strongly_connected_component_kosaraju --------- Co-authored-by: Rubal Singh <[email protected]>
1 parent 40c944c commit e9c28af

File tree

2 files changed

+98
-0
lines changed

2 files changed

+98
-0
lines changed
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
"""
2+
Implementing strongly connected components in a graph using Kosaraju's algorithm.
3+
https://en.wikipedia.org/wiki/Kosaraju%27s_algorithm
4+
"""
5+
6+
7+
class Kosaraju:
8+
"""
9+
Kosaraju's algorithm use depth first search approach to find strongly connected components in a directed graph.
10+
Approach:
11+
1. Make a DFS call to keep track of finish time of each vertex.
12+
2. Tranpose the original graph. ie 1->2 transpose is 1<-2
13+
3. Make another DFS call to calculate strongly connected components.
14+
"""
15+
16+
def dfs(self, i, V, adj, visited, stk):
17+
visited[i] = 1
18+
19+
for x in adj[i]:
20+
if visited[x] == -1:
21+
self.dfs(x, V, adj, visited, stk)
22+
23+
stk.append(i)
24+
25+
def kosaraju(self, V, adj):
26+
27+
stk, visited = [], [-1]*(V+1)
28+
29+
for i in range(V):
30+
if visited[i] == -1:
31+
self.dfs(i, V, adj, visited, stk)
32+
33+
stk.reverse()
34+
res = stk.copy()
35+
36+
ans, visited1 = 0, [-1]*(V+1)
37+
38+
adj1 = [[] for x in range(V)]
39+
40+
for i in range(len(adj)):
41+
for x in adj[i]:
42+
adj1[x].append(i)
43+
44+
for i in range(len(res)):
45+
if visited1[res[i]] == -1:
46+
ans += 1
47+
self.dfs(res[i], V, adj1, visited1, stk)
48+
49+
return ans
50+
51+
52+
def main():
53+
"""
54+
Let's look at the sample input.
55+
56+
6 7 #no of vertex, no of edges
57+
0 2 #directed edge 0->2
58+
1 0
59+
2 3
60+
3 1
61+
3 4
62+
4 5
63+
5 4
64+
65+
calculating no of strongly connected compnenets in a directed graph.
66+
answer should be: 2
67+
1st strong component: 0->2->3->1->0
68+
2nd strongly connected component: 4->5->4
69+
"""
70+
V, E = map(int, input().split())
71+
adj = [[] for x in range(V)]
72+
73+
for i in range(E):
74+
u, v = map(int, input().split())
75+
adj[u].append(v)
76+
77+
print(Kosaraju().kosaraju(V, adj))
78+
79+
80+
if __name__ == '__main__':
81+
main()

tests/test_graph.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
from algorithms.graph import cycle_detection
1515
from algorithms.graph import find_path
1616
from algorithms.graph import path_between_two_vertices_in_digraph
17+
from algorithms.graph import strongly_connected_components_kosaraju
1718

1819
import unittest
1920

@@ -349,3 +350,19 @@ def test_node_is_reachable(self):
349350
self.assertTrue(g.is_reachable(1, 3))
350351
self.assertFalse(g.is_reachable(3, 1))
351352

353+
class TestStronglyConnectedComponentsKosaraju(unittest.TestCase):
354+
def test_kosaraju_algorithm(self):
355+
V = 6
356+
adj = [
357+
[2],
358+
[0],
359+
[3],
360+
[1, 4],
361+
[5],
362+
[4]
363+
]
364+
365+
result = strongly_connected_components_kosaraju.Kosaraju().kosaraju(V, adj)
366+
367+
# Expected result: 2 strongly connected components
368+
self.assertEqual(result, 2)

0 commit comments

Comments
 (0)