Proofs: Kosaraju-Sharir algorithm
These are the human proofs of Kosaraju-Sharir algorithm, at full length.
The Kosaraju-Sharir algorithm labels each strongly connected component with its own number full
This proof shows: correctness, termination.
Let be a directed graph, where parallel arcs and loops are allowed. Write when has a directed path from to , and let the components be the classes of the relation " and ". Let and be the discovery and finish times of the DFS of line L1. For a set of vertices, let and . We use three facts from the depth-first search pages: the times are distinct; is a proper descendant of exactly when (the parenthesis theorem); and the white-path theorem.
Lemma 1. Let be components, and let have an arc with and . Then .
Proof. Let be the vertex of that is discovered first, so .
Case . Just before , every vertex of is white. Each is reachable from by a path that goes inside from to , takes the arc , and goes inside from to . The paths inside a component stay in the component (see strongly connected components), so this path is white, and by the white-path theorem is a descendant of . As , the parenthesis theorem gives . So .
Case . As above, each vertex of is a descendant of , so . No vertex of is reachable from : else , and and would be one component. A descendant of is reachable from by the tree path, so no vertex of is a descendant of . Let . Then , by the choice of . If , the intervals and would meet, so by the parenthesis theorem one would contain the other, and as the vertex would be a descendant of . So , and . Hence .
In the arc becomes , and has the same components as , because in exactly when in . So Lemma 1 reads:
Corollary 2. If has an arc from a component to another component , then .
Lemma 3 (what ASSIGN labels). Let be the set of vertices with $comp = $ NIL just before a call ASSIGN from line L7, with . When the call returns, the vertices labelled are exactly the vertices that has a path from to with all its vertices in . No other label changes.
Proof. ASSIGN is a depth-first search of that treats labelled vertices as already visited. Line L9 labels each vertex it is called on, line L11 calls it only on unlabelled vertices, so each vertex of is labelled at most once and the run stops after at most calls, each with a finite loop. Every labelled vertex is joined to by the chain of calls, which is a path inside . Conversely, let be a path of inside , and assume, for a contradiction, that some is not labelled at the end. Take the least such ; then , and was labelled by a call that scanned . At that moment was either unlabelled, and line L11 labelled it, or already labelled. A label set before the call is impossible, as , and a label set during the call is . Both contradict the choice of .
Theorem. KOSARAJU-SHARIR stops, and when it returns, if and only if and are in the same component. Moreover the labels are given to the components in decreasing order of , so for each arc of .
Proof. Lines L1 and L2 stop, and the loop of line L4 has steps, each of which stops by Lemma 3. We prove by induction on the steps of line L4 the invariant:
(K) The labelled vertices are the union of whole components , where is exactly the set labelled , and every component that is not labelled has for each . Also, every vertex that line L4 has already passed is labelled.
At the start, , no vertex is labelled and no vertex is passed, so (K) holds. Consider a step with vertex . If is labelled, nothing changes and becomes passed, so (K) holds. Else let be the component of . By (K), is not labelled at all, because the labelled set is a union of whole components and misses . We first show that and that has the largest among the unlabelled components. Line L4 takes the vertices in decreasing order of , and every vertex with a larger finish time than is passed and so labelled. So each unlabelled vertex has . Applied to the vertices of this gives , and applied to an unlabelled component it gives , with equality only if , as the times are distinct.
Now we show that ASSIGN labels exactly . Every vertex of is unlabelled and joined to by a path of inside , so by Lemma 3 it gets the label . Assume that some vertex outside gets this label. By Lemma 3, a path of from inside the unlabelled set reaches it, so this path has a first arc with and in another component , and is unlabelled. By (K), is then a whole unlabelled component, so by the paragraph above. But is an arc of from the component to the component , so Corollary 2 gives . This is a contradiction. So the set labelled is exactly , which we call , and every remaining unlabelled component has . Together with (K) for , which still holds because itself was unlabelled, the invariant holds after the step.
When the loop ends, every vertex is passed and so labelled, and by (K) each label class is exactly one component. This proves the first claim. By (K), . For an arc of with and in different components and , Lemma 1 gives , so . If they are in the same component, the labels are equal.
Remark on the second search. Lemma 3 holds for any search that labels exactly the vertices reachable from inside , so the theorem holds when ASSIGN is a breadth-first search or a search with an explicit stack, as in the Python implementation.