Proofs: Gabow's path-based strong component algorithm
These are the human proofs of Gabow's path-based strong component algorithm, at full length.
The path-based method pops exactly the strong components full
This proof shows: correctness.
Let be a directed graph; loops and parallel edges are allowed. Write when has a directed path from to , with always. At any moment of PATH-BASED-SCC, a vertex is new if , active if it is on , and done if it has a component. The call stack is the list of vertices whose VISIT has started and not ended; it is a path of the depth-first forest, and increases along it. Let and let be the vertex with . The block is the set of active with (with ).
We show that the following hold at each moment between lines.
- (I1) holds the active vertices in increasing preorder. Each is on the call stack, and every vertex on the call stack is active. If is not empty, of every active vertex, so the blocks partition the active vertices.
- (I2) Any two vertices of one block reach each other.
- (I3) If the edge has been scanned at line L5 and is active, then is done or is in the block of .
- (I4) Every edge out of a done vertex ends at a done vertex.
Also, (I5) when VISIT reaches line L9, , and is the only entry of that can be .
At the start every vertex is new, and all claims hold trivially.
Lines L3 and L4. The new vertex gets the largest preorder number so far, so pushing it keeps in preorder, and pushing keeps increasing. The new block is , and is on the call stack. Since is larger than every older number, no older vertex changes block. (I2) to (I4) are untouched.
Proof of (I5). At line L4 the top of is . Each child call VISIT from line L6 ends, by (I5) for and lines L9 to L11, with every entry of at most and with the entry itself removed if it was there; so its pushes are gone and all entries are again at most the entries present before the call. Line L8 only pops. So at line L9 every entry is at most , and the entries pushed before are smaller. This also shows the first part of (I1) for : after VISIT ends, no entry equals , so every entry belongs to a vertex still on the call stack.
Line L8. Here is the current vertex, the last on the call stack, and is active, say . By (I1) is in the top block , since (the entry belongs to a vertex on the call stack, which is an ancestor of or ). We show that all vertices of reach each other. For each with , the vertex is a descendant of in the forest, since both are on the call stack, so , and also . By (I2) each vertex of reaches and back. So every vertex of these blocks reaches through . Conversely, is an edge, by (I2), and reaches every with and hence every vertex of . So the union is mutually reachable. Line L8 pops exactly , the entries greater than , because . This merges into one block and keeps (I2). Merging only unites blocks, so (I3) stays true. After this step is in the block of , which gives (I3) for the edge .
The other cases of an edge . If is done, (I3) holds for this edge. If was new, VISIT runs and returns; then is done, or is active with by (I5) for the call of and since all entries now belong to the call stack, which ends at . Then and are both in the top block, and (I3) holds.
Lines L9 to L11. Suppose . The top block is , and by (I1) these are exactly the entries of from to the top, which line L11 pops. Each was reached after and before the end of VISIT, so or is a descendant of whose VISIT has ended; in both cases all edges out of have been scanned. By (I3), each edge out of ends in or at a done vertex, and by (I4) a done vertex reaches only done vertices. So every vertex reachable from is in or done, and no done vertex reaches . Hence the strong component of lies in , and by (I2) it contains . So line L11 gives one strong component the label . Afterwards (I4) holds: the edges out of the new done vertices end in or at done vertices. (I1) holds because the popped vertices are exactly the vertices with , and leaves the call stack. If , nothing changes, and stays active in a block whose first vertex is a proper ancestor of , so (I1) still holds after leaves the call stack.
Theorem. PATH-BASED-SCC labels each vertex with its strong component, and the labels are in reverse topological order of the condensation.
Proof. Line L2 starts VISIT at every vertex that is still new, so every vertex is reached. When the outer call VISIT reaches line L9, the call stack is alone, so by (I1) and (I5) and the test holds; every active vertex is popped. So when line L2 ends, every vertex is done, and by the case of lines L9 to L11 each label class is one strong component. Each component gets one label, because its vertices leave together. If an edge leads from a component to a different component , then at the moment closes, every edge out of ends at a done vertex, so closed earlier and has a smaller label. Each line runs a bounded number of times per vertex or per edge, so the method also ends.