Algorithm Search⌘K

Proofs: Online bridge finding

These are the human proofs of Online bridge finding, at full length.

Online bridge finding keeps the 2-edge-connected components and the bridge forest full

This proof shows: correctness.

Let GG be the current multigraph. An edge is a bridge if it lies on no cycle, which is the same as: removing it increases the number of connected components. Two vertices are 2-edge-connected if they are equal or joined by two edge-disjoint paths; this is an equivalence relation, and its classes are the 2-edge-connected components. The edges between different classes are exactly the bridges, and contracting each class gives a forest F(G)F(G), the bridge forest, whose edges are the bridges [standard facts; see the page on two-edge-connected components].

Invariant (B). (1) The sets of EE are the 2-edge-connected components of GG. (2) The representatives with their pointers E.find(par(a))E.\mathrm{find}(\mathrm{par}(a)) form a rooted forest isomorphic to F(G)F(G). (3) The sets of CC are the connected components of GG, each with its number of vertices, and every vertex of a tree of the forest finds the same CC-root. (4) The counter equals the number of bridges of GG.

At the start GG has no edges, every vertex is its own component and its own tree, and there are no bridges, so (B) holds. Assume (B) before ADD-EDGE(u,v)(u, v), and let G′=G+{u,v}G' = G + \{u, v\}, a=E.find(u)a = E.\mathrm{find}(u), b=E.find(v)b = E.\mathrm{find}(v).

Case 1: a=ba = b (line L1). Then uu and vv are 2-edge-connected in GG. Adding an edge between them creates no new connection between classes and adds no cycle through a bridge: a cycle in G′G' through a bridge ee of GG would use the new edge, and replacing the new edge by a path inside the class of uu that avoids ee (the class has no bridges inside it, and ee is not inside it) gives a closed walk in GG through ee once, so a cycle through ee in GG, a contradiction. So the classes and the bridges are unchanged, and nothing changes.

Case 2: a≠ba \ne b and different connected components (lines L3 to L5). The new edge joins two components of GG, so it lies on no cycle of G′G': a cycle through it would need another path between the two components. So it is a bridge of G′G'. Every old bridge stays a bridge, because a cycle of G′G' that uses an old edge cannot use the new bridge, so it would be a cycle of GG. Every class is unchanged, because the new edge adds no edge-disjoint pair of paths between any two vertices. So F(G′)F(G') is F(G)F(G) plus the edge between the classes aa and bb, and the counter is right after line L3. REROOT(a)(a) (line L9) reverses the pointers on the path from aa to the root of its tree: this is the same tree rooted at aa, so (B2) still holds with aa as the root. Setting par(a)←b\mathrm{par}(a) \leftarrow b hangs that tree below bb, which adds exactly the new bridge to the forest. The union in CC merges the two connected components and adds their sizes. In the implementation, REROOT also points the CC-entries of the path and the old CC-root at aa, so all vertices of the rerooted tree reach the root aa, and then aa points to bb; this keeps (B3).

Case 3: a≠ba \ne b in the same connected component (line L6). Then aa and bb are in one tree TT of the forest by (B2) and (B3). Let PP be the path a=x0,x1,…,xk=ba = x_0, x_1, \ldots, x_k = b in TT, through the lowest common ancestor ll, and let e1,…,eke_1, \ldots, e_k be its bridges.

Line L7 finds ll. The climbs visit the ancestors of aa and of bb in order of distance. A component is marked twice only if it is an ancestor of both, and the first common ancestor reached by either climb is ll: a climb reaches ll before any higher common ancestor, and when one climb reaches a component already marked by the other, that component is a common ancestor; the first such is the lowest one on the climbing side, which is ll, since every proper ancestor of ll is above ll on both sides.

The new classes. Each bridge eie_i lies on a cycle of G′G': take the new edge, then a path in GG from vv to uu that crosses the classes of PP in order and uses each eie_i once (it exists because each class is connected). So no eie_i is a bridge of G′G', and the classes x0,…,xkx_0, \ldots, x_k become one 2-edge-connected class of G′G': any two of their vertices are joined by two edge-disjoint paths, around the new cycle and inside the classes. Every other bridge ff of GG is not on PP, so it still separates TT into two parts, one of which contains all of PP; any cycle of G′G' through ff would use the new edge, whose ends are both in the other part, so it would cross ff twice, which a cycle cannot. So ff stays a bridge, and the other classes do not change.

Line L8 unions exactly the classes xi≠lx_i \ne l on PP into the class of ll and decreases the counter once per class merged, that is, kk times, once per bridge eie_i. So (B1) and (B4) hold. In F(G′)F(G'), the merged class is adjacent to the parent of ll and to the children of the classes of PP that are not on PP. The merged representative takes the parent of ll, and the children of the other classes of PP still point to vertices of those classes, which now find the merged representative. So (B2) holds. The connected components do not change, and the CC-pointers still lead to the same root, so (B3) holds.

Queries. By (B1), two vertices are 2-edge-connected if and only if E.findE.\mathrm{find} gives the same representative, and an inserted edge is a bridge if and only if its ends are in different classes. By (B3) and (B4), the connectivity queries and the bridge count are right. ■\blacksquare

Back to Online bridge finding