3 Algorithm to find strongly connected components of a
directed graph
The algorithm we present is essentially two passes of depth-first search, plus some extremely
clever additional book-keeping. The algorithm is described in a top-down fashion in Algo-
rithms 1 to 3. Algorithm 1 describes the top level of the algorithm, and Algorithm 2 and
Algorithm 3 describe the subroutines DFS-Loop and DFS. Read these procedures carefully
before proceeding to the next section.
Algorithm 1: The top level of our SCC algorithm. The f -values and leaders are computed
in the first and second calls to DFS-Loop, respectively (see below).
Input : A directed graph G = (V, E), in adjacency list representation. Assume that the
vertices V are labeled 1, 2, 3, . . . , n.
G
rev
← the graph G after the orientation of all arcs have been reversed.
Run the DFS-Loop subroutine on G
rev
, processing vertices in any arbitrary order, to
obtain a finishing time f (v) for each vertex v ∈ V .
Run the DFS-Loop subroutine on G, processing vertices in decreasing order of f (v), to
assign a “leader” to each vertex v ∈ V . The leader of a vertex v will be the source
vertex that the DFS that discovered v started from.
The strongly connected components of G correspond to vertices of G that share a
common leader.
Remark 4. The algorithm in Algorithm 1 is a bit different than the one in CLRS/Lecture!
The difference is that in these notes, we first run DFS on the reversed graph, and then we
run it again on the original; in CLRS, we first run DFS on the original, and then the second
time on the reversed graph. Is it the case that one of these two textbooks has messed it
up? In fact, it doesn’t matter: the SCCs of G are the same as the SCCs of G
r ev
, so both
algorithms find exactly the same SCC decomposition.
As we’ve seen, each invocation of DFS-Loop can be implemented in linear time (i.e., O(|E| +
|V |)), so this whole algorithm will take linear time (the bookkeeping of leaders and finishing
times just adds a constant number of operations per each node).
4 An Example
But why on earth should this algorithm work? An example should increase its plausibility
(though it certainly doesn’t constitute a proof of correctness). Figure 2 displays a reversed
graph G
rev
, with its vertices numbered arbitrarily, and the f -values computed in the first call
to DFS-Loop. In more detail, the first DFS is initiated at node 9. The search must proceed
next to node 6. DFS then has to make a choice between two different adjacent nodes; we
have shown the f -values that ensue when DFS visits node 3 before node 8.
1
When DFS visits
1
Different choices of which node to visit next generate different sets of f -values, but our proof of correctness
will apply to all ways of resolving these choices.
3