Proofs: Hopcroft-Tarjan biconnectivity algorithm
These are the human proofs of Hopcroft-Tarjan biconnectivity algorithm, at full length.
One depth-first search finds the articulation points, the bridges and the blocks full
This proof shows: correctness.
Let be an undirected graph. Parallel edges and loops are allowed, and every edge has its own identifier. Loops are output as blocks by line L2 and are skipped by the search (the test of line L6); a loop lies on no cycle with another edge and changes no articulation point and no bridge, so from here on has no loops.
Depth-first search facts. The calls of line L3 build a depth-first forest. An edge is a tree edge if it is pushed by line L8, and every other edge is a back edge. Since the search skips the tree edge into only by its identifier, a parallel copy of a tree edge is a back edge. Each back edge joins a vertex to a proper ancestor of (edge classification); we call its lower end. For a tree edge, the lower end is the child. Write for the subtree of , and
Lemma 1. When VISIT returns, .
Proof. By induction on the order in which the calls return. Line L5 sets . Each edge at other than is one of three kinds. If , it becomes a tree edge, and line L9 takes the minimum with by induction. If , is an ancestor of , so is a back edge with lower end , and line L15 takes . If , is a descendant of that is already visited, so is a back edge with lower end , already counted in of a child; its value is not below anyway. So is the minimum over , its own back edges and the subtrees of its children, which is .
Lemma 2 (where an edge out of a subtree can go). Let be a tree edge. Every edge with exactly one end in is the tree edge or a back edge from a vertex of to a proper ancestor of , and the smallest discovery time among the ends of such back edges is when it is below .
Proof. A tree edge with one end in is . A back edge joins a vertex to an ancestor, so if one end is in and the other is not, the lower end is in and the upper end is an ancestor of outside . The rest is the definition of .
Theorem 1 (bridges, line L13). An edge is a bridge if and only if it is a tree edge with .
Proof. A back edge from to lies on the cycle formed with the tree path from to , so it is not a bridge. For a tree edge , the graph joins to the rest if and only if some other edge has exactly one end in . By Lemma 2, such an edge is a back edge from to an ancestor of (possibly itself, through a parallel copy of ), which has . So is not a bridge if and only if . Lemma 1 finishes the proof.
Theorem 2 (articulation points, lines L4 and L12). A root is an articulation point if and only if it has at least two children. A vertex that is not a root is one if and only if it has a child with .
Proof. Root. By Lemma 2 no edge joins the subtrees of two children of , since a back edge goes to an ancestor. With two or more children, splits them. With one child , contains the tree , which spans the rest of the component.
Not a root. Suppose a child has . By Lemma 2, every edge that leaves goes to an ancestor of with , so to . In , the set has no edge to the root , so is an articulation point. Conversely, suppose every child has . Then each has a back edge to a proper ancestor of . The vertices of the component that are not in form a subtree that contains , so they stay connected in , and each is joined to them. So has as many components as .
Theorem 3 (blocks, line L11). Each block of is output exactly once, as the set of edges popped by line L11.
Proof. Call a vertex that is not a root a head if , where is the parent of ; these are the children for which line L10 succeeds. Every child of a root is a head. For an edge with lower end , let be the first head on the tree path from up to the root, starting at . Let be without the subtrees of the heads inside .
Step 1: line L11 pops exactly the edges with when it closes the tree edge . The edges pushed from the push of until VISIT returns are the edges whose lower end is in , since line L8 and line L15 push an edge when its lower end is the current vertex. The pops for heads inside happen earlier, since a call returns after its descendants; by induction they removed the edges whose is such a head. The remaining edges above on the stack are those with .
Step 2: all ends of an edge with lie in . The lower end is in . If is a back edge to , then , so is on the tree path from to ; an inner vertex of this path in some would put in too, so .
Step 3: two edges on a common cycle have the same . Let be a head. By Lemma 2 and , every edge with exactly one end in has its other end at . A cycle that enters must enter and leave it through , and it passes only once, so the whole cycle lies in . So every cycle either lies in or has no vertex in . Take the deepest head with ; it exists because lies in the subtree of one child of a root. Every head inside has disjoint from , so all lower ends of edges of are in , and all edges of have .
Step 4: the edges with are pairwise on common cycles. Write . Let be a tree edge with and . Then is not a head, so , and some back edge goes from to a proper ancestor of . If were in for a head inside , the edge would end at , which is not an ancestor of ; so . The cycle of this back edge and the tree path contains and the tree edge into . So by induction upward, every tree edge with lower end in lies on a common cycle with , in the sense of the relation of the biconnected components page. A back edge with from to lies on a cycle with the first tree edge below on the path to , and by Step 2 that tree edge has its lower end in . Since is transitive, all edges with are in one class.
Steps 3 and 4 show that the classes of on the non-loop edges are exactly the sets for the heads , each one non-empty because it contains . Step 1 shows that line L11 outputs each of these sets once.
Termination and output. Each vertex is visited once, each list entry is read once, and each non-loop edge is pushed once and popped once. So the procedure stops, it outputs every block once (Theorem 3 and line L2), and it marks exactly the articulation points and the bridges (Theorems 1 and 2).