What is Kosaraju’s strongly connected component algorithm?

In computer science and graph theory, identifying strongly connected components (SCCs) in directed graphs is a pivotal task with wide-ranging applications, from social network analysis to web page rankings and compiler optimizations. One of the efficient solutions to this problem is Kosaraju’s algorithm.

Key takeaways:

Here’s what you will learn after reading the article on Kosaraju’s SCC Algorithm:

  1. What SCCs are, and why they are essential for analyzing directed graphs.

  2. How this algorithm efficiently finds all SCCs using two DFS passes and graph transposition.

  3. A detailed breakdown of the two phases of Kosaraju’s algorithm—first for recording node finishing times and second for identifying SCCs in the transposed graph.

  4. A Python implementation of the algorithm and how it translates to solving real-world graph-based problems.

  5. The practical applications of SCC detection in areas like social networks and compiler optimization, along with its time complexity O(V + E).

Introduction to strongly connected components

A strongly connected component (SCC) in a directed graph is a maximal subgraph wherein each vertex is reachable from every other vertex in the same subgraph. This means that for any two nodes A and B in a subgraph, there is a path from A to B and a path from B to A. This concept is crucial for analyzing the connectivity and clustering within networks.

Example of SCCs

canvasAnimation-image

Kosaraju’s algorithm overview

Developed by S. Rao Kosaraju in the late 1970s, Kosaraju’s algorithm is appreciated for its simplicity and efficiency in identifying all SCCs in a directed graph. It operates in two main phases, each involving a complete traversal of the graph:

  1. A depth-first search (DFS) determines nodes’ finishing times.

  2. Transposing the graph followed by another DFS guided by the previously obtained finishing times.

The finishing time refers to the point at which a node (vertex) has been fully explored during the DFS traversal. Specifically, it is the time when:

  1. The algorithm finishes exploring all of the node’s descendants (i.e., all reachable vertices from that node) and,

  2. The DFS is about to backtrack from that node.

Example of finding SCCs using Kosaraju’s algorithm

canvasAnimation-image
1 of 15

Step-by-step explanation of the algorithm

Phase 1: Depth-first search and finishing times

This phase includes two main steps:

  1. Perform DFS: Initiate DFS from any unvisited vertex, exploring as far as possible along each branch before backtracking.

  2. Record finishing times: Maintain a stack where vertices are pushed based on finishing times, i.e., the vertex finishing the exploration last is pushed first.

Phase 2: Transpose and discover SCCs

This phase includes three main steps:

  1. Transpose the graph: Create a new graph by reversing the direction of all edges in the original graph.

  2. DFS–based on finishing times: Pop vertices from the stack (starting with the vertex that finished last in the original graph) and perform DFS in the transposed graph. Each DFS run from a vertex identifies a new SCC.

  3. Identify SCCs: Vertices reached during a single DFS call constitute an SCC.

Kosaraju’s strongly connected component algorithm

Question 1

You’re working on a social media platform, and you need to analyze clusters of users who are mutually connected. How can Kosaraju’s algorithm help with this?

Show Answer
Question 2

You are developing a compiler, and one task is to optimize loops in a program. You need to find groups of code blocks that depend on each other circularly. Which graph algorithm would be helpful?

Show Answer

Code example

Here’s a Python code snippet that implements Kosaraju’s algorithm:

from collections import defaultdict
class Graph:
def __init__(self, vertices):
self.V = vertices
self.graph = defaultdict(list)
def add_edge(self, src, dest):
# Add a source vertex to destination vertex
self.graph[src].append(dest)
# Fill vertices in stack according to their finishing times in DFS
def fill_order(self, v, visited, stack):
visited[v] = True
for i in self.graph[v]:
if not visited[i]:
self.fill_order(i, visited, stack)
stack.append(v) # Corrected: Just append, no reassignment
# Perform DFS to get strongly connected components
def depth_first_search(self, v, visited, scc):
visited[v] = True
scc.append(v)
for neighbor in self.graph[v]:
if not visited[neighbor]:
self.depth_first_search(neighbor, visited, scc)
# Transpose the graph (reverse the direction of all edges)
def transpose(self):
g = Graph(self.V)
for v in self.graph:
for neighbor in self.graph[v]:
g.graph[neighbor].append(v)
return g
# Function to print all SCCs
def print_scc(self):
stack = []
visited = [False] * self.V
# Fill the stack with vertices based on finishing times
for i in range(self.V):
if not visited[i]:
self.fill_order(i, visited, stack)
# Transpose the graph
gr = self.transpose()
# Mark all vertices as not visited for the second DFS
visited = [False] * self.V
# Process all vertices in the order defined by the stack
while stack:
v = stack.pop()
if not visited[v]:
scc = []
gr.depth_first_search(v, visited, scc)
print("Strongly Connected Component:", scc)
# Example usage
g = Graph(9)
g.add_edge(0, 1)
g.add_edge(1, 2)
g.add_edge(2, 3)
g.add_edge(3, 0)
g.add_edge(2, 4)
g.add_edge(4, 5)
g.add_edge(5, 6)
g.add_edge(6, 4)
g.add_edge(6, 7)
g.add_edge(7, 8)
g.print_scc()

Explanation

Here’s the updated explanation based on the corrected code:

  • Lines 3–6: The Graph class is defined, which initializes the number of vertices (VV) and an adjacency list (graph) to represent the directed graph.

  • Lines 8–10: The add_edge() method adds a directed edge from the source vertex (src) to the destination vertex (dest) by appending the destination to the adjacency list of the source.

  • Lines 12–18: The fill_order() method performs a depth-first search (DFS) to determine the order in which vertices should be processed. It starts from vertex v, marks it as visited, and recursively visits all unvisited neighbors. Once all reachable vertices from v have been explored, the current vertex is pushed onto the stack, storing the order of completion (finishing times).

  • Lines 20–26: The transpose() method generates a transposed version of the graph. It reverses the direction of all edges in the original graph by iterating over each vertex and its neighbors and adding the reversed edges to a new graph instance.

  • Lines 28–34: The depth_first_search() method is used for identifying strongly connected components (SCCs). It starts from a vertex v, marks it as visited, and explores all unvisited neighbors, appending vertices to a list (scc) that represents the current SCC.

Key parts of the code:

  • Stack for finishing times: The first DFS ensures vertices are processed based on the order in which they finish their DFS exploration.

  • Transposed graph: The graph is reversed, which allows the second DFS to find SCCs by processing nodes in reverse finishing order.

  • SCC detection: Each strongly connected component is discovered during the second DFS on the transposed graph.

Complexity analysis

The time complexity of Kosaraju’s algorithm is O(V+E)O(V+E), where VV is the number of vertices and EE is the number of edges due to the two DFS passes and the graph transposition. This efficiency makes it highly suitable for large graphs.

Quiz

Kosaraju’s strongly connected component algorithm

1

What is the purpose of Kosaraju’s algorithm in graph theory?

A)

To find the shortest path between nodes.

B)

To identify strongly connected components in directed graphs.

C)

To calculate the minimum spanning tree.

D)

To detect cycles in an undirected graph.

Question 1 of 30 attempted

Conclusion

Kosaraju’s algorithm remains a fundamental and efficient method for identifying strongly connected components in directed graphs. Its simplicity and optimal performance, backed by a clear Python implementation, illustrate its practical applications and robustness in handling complex graph-based problems.

Practice resources for LeetCode problems

To further strengthen your coding skills and boost your technical interview preparation, here are some Graph problems to practice:

Also, you can explore these courses designed specifically to help you ace technical interviews:

Moreover, if you’re confident in your preparation, consider trying Educative’s AI-powered mock interviewsMock interviews are excellent for building confidence, sharpening problem-solving skills, and identifying areas to improve before the actual interview.

Frequently asked questions

Haven’t found what you were looking for? Contact Us


What is Kosaraju’s algorithm used for?

Kosaraju’s algorithm is used to find all strongly connected components (SCCs) in a directed graph. An SCC is a maximal subgraph where every vertex is reachable from every other vertex within the subgraph.


What is a transposed graph, and why is it important in Kosaraju’s algorithm?

A transposed graph is created by reversing the direction of all edges in the original graph. It is important in Kosaraju’s algorithm because SCCs in the transposed graph correspond to the SCCs in the original graph, and the second DFS identifies them based on the finishing times of the first DFS.


Can Kosaraju’s algorithm be applied to undirected graphs?

No, Kosaraju’s algorithm is specifically designed for directed graphs. SCCs do not exist in undirected graphs, where the concept of connected components is used instead.


How does Kosaraju’s algorithm compare to Tarjan’s algorithm?

Both algorithms are used to find SCCs, but Kosaraju’s algorithm uses two DFS traversals (with graph transposition), while Tarjan’s algorithm finds SCCs in a single DFS traversal using a stack-based approach. Both have the same time complexity of O(V + E).


Free Resources

HowDev By Educative. Copyright ©2025 Educative, Inc. All rights reserved