Proofs: Gabow-Myers spanning tree enumeration algorithm
These are the human proofs of Gabow-Myers spanning tree enumeration algorithm, at full length.
The Gabow-Myers backtracking lists every spanning tree exactly once full
This proof shows: correctness, termination.
Let be a finite undirected graph with , . Parallel edges are distinct edges, and self-loops are allowed. During the run, some edges are deleted. The current graph is without the deleted edges. For an edge set , let be the set together with the ends of the edges of . An edge leaves if it has exactly one end in .
Facts
Fact 1. Let be a connected graph, and let be a set of edges of that forms a tree on . Then some spanning tree of contains .
Proof. Start from . While the edge set does not span , some edge of leaves the set of reached vertices, because is connected. Adding it keeps the set a tree. After steps, the set is a spanning tree that contains .
Fact 2. If is a tree on , then every spanning tree of a graph contains an edge of that leaves .
Proof. connects a vertex of to a vertex outside it, and the path between them in has an edge that leaves .
The invariant
Call a state of a call GROW good if the following hold:
- (a) is a tree on , and .
- (b) is connected.
- (c) holds exactly the edges of that leave , each once.
Lemma. If GROW is called in a good state, then it terminates. It outputs each spanning tree of that contains exactly once, and nothing else. On return, and are as they were at the call.
Proof. By induction on .
Base, . By (a), is a tree with edges, so it is a spanning tree. It is the only spanning tree that contains . Line L1 outputs it and returns without changing anything.
Step, . Then . Let be the current graph at the call. Let be the edges popped at line L4 in the successive iterations, and let be the current graph at the start of iteration . Line L8 gives , and line L7 together with the induction hypothesis gives that the recursive call changes nothing. We show by induction on that iteration starts with connected and with equal to the set of edges of that leave .
For , this is (b) and (c). Suppose it holds for . The graph is connected and , so some edge of leaves , and is not empty. So line L4 pops an edge with and . Line L5 removes the edges of that join to and adds the edges of from to . Afterwards holds exactly the edges of that leave . The set is a tree on that vertex set, because adds the new vertex . So the call at line L6 is made in a good state, with , and the induction hypothesis applies. Line L7 restores to the edges of that leave , minus . Line L8 deletes . So is now the set of edges of that leave . If the loop continues, then is connected, by the test at lines L9 and L10. This completes the induction on .
Termination. Each iteration deletes an edge of the finite graph , and each recursive call terminates by the induction hypothesis. So the loop runs at most times. Let be the number of iterations. Then is disconnected.
What is output. By the induction hypothesis, iteration outputs exactly the spanning trees of that contain , each once. These are the spanning trees of with , and . Call this set .
- Disjoint. If , every tree in contains and every tree in avoids it. So no tree is output twice.
- Complete. Let be a spanning tree of with . If contains none of , then is a spanning tree of the disconnected graph , which is impossible. So contains some . Taking the least such gives .
- Only trees that contain . Every output tree lies in some .
Restoration. Line L11 undeletes , so the current graph is again. It pushes back onto , with on top, which reverses the pops of line L4. Lines L7 and L8 left the rest of as it was. So is as it was at the call.
The theorem
Theorem. If is connected, the top-level call outputs each spanning tree of exactly once and terminates. If is disconnected, it outputs nothing.
Proof. If is disconnected, it has no spanning tree, and the top level returns before calling GROW. Otherwise, the call GROW, with the non-loop edges at vertex 0, is made in a good state. is a tree on , is connected, and the edges that leave are exactly the non-loop edges at 0. Every spanning tree contains . The lemma then gives the claim.
Corollary (no dead ends). Every call of GROW outputs at least one tree.
Proof. Every call is made in a good state. By Fact 1, the connected graph has a spanning tree that contains , and the lemma says the call outputs it.
So the recursion tree has leaves, its depth is at most , and it has at most nodes. This is the count used in the complexity analysis. Fact 2 is the reason the loop can stop at a bridge: once is disconnected, no remaining tree avoids .