Tarjan's Algorithm
Think about a social network where some groups of friends are so tightly connected that everyone can reach everyone else — directly or through mutual friends. These are cliques of mutual reachability. In a directed graph, we call them Strongly Connected Components (SCCs).
Formally: an SCC is a maximal set of vertices where for every pair u and v, there's a directed path from u to v AND from v to u. Tarjan's algorithm finds all SCCs in a single depth-first search — no need to traverse the graph twice or build a transposed copy.
Discovery and Low-Link Values
Tarjan's DFS tracks two numbers per vertex:
- disc[u] — the DFS discovery time (a clock that ticks up each time we visit a new vertex)
- low[u] — the lowest discovery time reachable from u's DFS subtree via tree edges and at most one back edge (an edge to an ancestor still on the DFS stack)
Initially low[u] = disc[u]. As DFS explores neighbors:
- If neighbor v is unvisited: recurse, then set
low[u] = min(low[u], low[v]) - If neighbor v is on the DFS stack (a back edge): set
low[u] = min(low[u], disc[v])
The Stack and SCC Detection
Every vertex is pushed onto an auxiliary stack when first visited. The key insight: when DFS finishes a vertex u (all its descendants are done), check if low[u] == disc[u].
If yes, u is the root of an SCC — no path from u's subtree escapes to an ancestor. Pop everything from the stack down to and including u — that's one complete SCC.
If low[u] < disc[u], some descendant of u can reach an ancestor of u, so u is not the root of its own SCC — it belongs to a larger component.
What the Condensation DAG Reveals
Once all SCCs are found, replace each SCC with a single super-node. The resulting graph — the condensation DAG — is always acyclic (since cycles within components were already collapsed). This DAG captures the high-level structure: which components can reach which others. It's the foundation for further algorithms like topological sort on the component level.
Extensions: Bridges and Articulation Points
The same DFS framework works on undirected graphs to find:
- Bridge: edge (u, v) is a bridge if
low[v] > disc[u]— removing it disconnects the graph - Articulation point: vertex u is an articulation point if removing it disconnects the graph (different condition for root vs. non-root)
All of these can be found in the same single DFS pass — \(O(V+E)\) total.