Tarjan's algorithm finds every strongly connected component in a directed graph with a single DFS pass. It does not need to reverse the graph or run a second traversal, which is what Kosaraju's algorithm requires.
The same core idea also gives us bridges, articulation points, and 2-edge-connected components. These show up in network reliability problems, compiler optimization (finding loops in control flow graphs), and graph interview questions.
This chapter walks through how Tarjan's algorithm works, traces it step by step on a sample graph, and then extends the core idea to find bridges and articulation points.
Tarjan's algorithm is a depth-first search based algorithm that finds all strongly connected components (SCCs) in a directed graph in O(V + E) time using a single pass.
A strongly connected component is a maximal group of vertices where every vertex can reach every other vertex through directed edges. "Maximal" means you cannot add any more vertices to the group without breaking this property.
Consider this directed graph:
There are two SCCs here: {A, B, C} and {D, E}. Within {A, B, C}, you can follow directed edges from any vertex to any other. Same for {D, E}. But you cannot get from D or E back to A, B, or C, so these two groups remain separate components.
Robert Tarjan published this algorithm in 1972. The key insight is that during a single DFS, you can gather enough information to identify all SCCs without needing a second pass.
Tarjan's algorithm relies on two values tracked for every vertex during the DFS traversal.
The discovery time of a vertex is the order in which DFS first visits it. The first vertex visited gets disc = 0, the second gets disc = 1, and so on. This timestamps when each vertex was discovered.
The low-link value of a vertex u is the smallest discovery time reachable from u (or any descendant of u in the DFS tree) by traveling down any number of tree edges and then taking at most one non-tree edge to a vertex still on the SCC stack. That non-tree edge can be a back edge to an ancestor or a cross edge to a vertex in a sibling subtree, as long as the target is still on the stack (meaning it has not yet been assigned to a completed SCC).
Initially, low[u] = disc[u] for every vertex u. As the DFS explores neighbors, low[u] gets updated if a path back to an earlier vertex is found. The difference between the two values is what Tarjan's relies on: disc[u] never changes after a vertex is first visited, while low[u] can drop as the search discovers a route back to an ancestor. When low[u] stays equal to disc[u], no such route exists, and u is the entry point of its component.
A vertex u is the root of a strongly connected component if disc[u] == low[u]. This means that u cannot reach any vertex discovered earlier than itself, which means u is the "entry point" of its SCC in the DFS tree.
When this condition is met, everything on the stack from u to the top forms one complete SCC.
In this diagram, vertex u has disc = 2 and low = 2, making it the root of the SCC. Vertices v and w both have low = 2 because they can reach u (discovered at time 2) through the back edge from w to u. All three vertices form one SCC.
Here is the algorithm in plain English:
The stack does the central work here. It holds all vertices in the current DFS path that have not yet been assigned to an SCC. When we find a root (disc == low), we know everything above it on the stack belongs to the same SCC.
Here is the full implementation of Tarjan's algorithm for finding strongly connected components.
Let us trace Tarjan's algorithm on a directed graph with 8 vertices and 3 SCCs.
The three SCCs are: {0, 1, 2}, {3, 4, 5}, and {6, 7}. Let us see how the algorithm discovers them.
Step 1: Visit vertex 0
Step 2: Visit vertex 1
Step 3: Visit vertex 2
Step 4: Visit vertex 3
Step 5: Visit vertex 4
Step 6: Visit vertex 5
Step 7: Visit vertex 6
Step 8: Visit vertex 7
Step 9: Back at vertex 6
Step 10: Back at vertex 5
Step 11: Back at vertex 4
Step 12: Back at vertex 3
Step 13: Back at vertex 2
Step 14: Back at vertex 1
Step 15: Back at vertex 0
Final state:
| Vertex | disc | low | SCC |
|---|---|---|---|
| 0 | 0 | 0 | {0, 1, 2} |
| 1 | 1 | 0 | {0, 1, 2} |
| 2 | 2 | 0 | {0, 1, 2} |
| 3 | 3 | 3 | {3, 4, 5} |
| 4 | 4 | 3 | {3, 4, 5} |
| 5 | 5 | 3 | {3, 4, 5} |
| 6 | 6 | 6 | {6, 7} |
| 7 | 7 | 6 | {6, 7} |
Within each SCC, all vertices share the same low-link value, and that value equals the disc value of the SCC's root.
The same disc and low values from Tarjan's algorithm can be used to find bridges in an undirected graph. A bridge is an edge whose removal disconnects the graph (or increases the number of connected components).
An edge (u, v) is a bridge if low[v] > disc[u]. This condition means that vertex v has no way to reach u or any ancestor of u without using the edge (u, v). Removing that edge would therefore disconnect v's subtree from the rest of the graph.
In this graph, the edge (2, 3) is a bridge. Vertices {0, 1, 2} form a cycle, so removing any edge between them still keeps them connected. But the only way to reach vertex 3 from vertices {0, 1, 2} is through that single edge.
Here is the implementation for finding bridges:
Key differences from the SCC version:
An articulation point (or cut vertex) is a vertex whose removal disconnects the graph. The logic is similar to finding bridges but with a slightly different condition.
A vertex u is an articulation point if either:
In this graph, vertex 1 is an articulation point. Remove it, and {0, 2} gets disconnected from {3, 4}.
Here is the implementation for finding articulation points:
Using a set for articulation points avoids duplicates, since a vertex might satisfy the condition for multiple children.
Both algorithms find strongly connected components in O(V + E) time, but they take different approaches.
| Aspect | Tarjan's | Kosaraju's |
|---|---|---|
| Number of DFS passes | 1 | 2 |
| Needs graph reversal | No | Yes |
| Extra data structures | Stack + disc/low arrays | Stack + reversed graph |
| Space overhead | O(V) | O(V + E) for reversed graph |
| Conceptual complexity | Higher | Lower |
| Output order | Reverse topological order | Topological order |
| Handles undirected graphs | With modifications (bridges, APs) | Not directly |
When to prefer Tarjan's:
When to prefer Kosaraju's:
Tarjan's algorithm runs in O(V + E) time. It performs a single depth-first search that visits each vertex once and examines each edge once, computing the discovery and low-link values during that traversal. The bridge-finding and articulation-point variants reuse the same single DFS, so they also run in O(V + E).
The algorithm uses O(V) space. It stores the disc and low arrays, an on-stack boolean array, and the explicit stack, each holding at most V entries, plus the recursion stack, which can grow to O(V) in the worst case. Storing the graph as an adjacency list takes O(V + E).
10 quizzes