Gusfield's algorithm for Gomory–Hu trees #
Gusfield ([Gus90]) showed that a Gomory–Hu tree can be computed with n - 1 minimum cut
computations in the original graph, without the contractions of Gomory and Hu's construction
([GH61]). The tree is kept as a parent function p with root r. Initially every vertex
hangs from r. The other vertices s are processed once each: with t = p s and a minimum
s–t cut X, every other vertex whose parent is t and which lies in X is re-hung below s,
and if the parent of t lies in X, then s takes the place of t (p s := p t, p t := s).
This module states the algorithm for an arbitrary cut oracle and an arbitrary processing order,
and proves it correct for every symmetric submodular set function: if the oracle returns minimum
cuts, the final parent graph is a Gomory–Hu tree. The oracle may return any minimum cut. The
executable version over Fin n with Edmonds–Karp as the oracle, and its running time, are in
CslibFrontier.Algorithms.Lean.GomoryHu.Construction.
Proof #
After processing a set P ∋ r of vertices, the invariant is: the parent of every vertex is in
P; every i ∈ P other than r carries a minimum i–p i cut S i that no other parent pointer
crosses (z ∈ S i ↔ p z ∈ S i for z ≠ i); and every vertex is joined to r by parent pointers.
To process s ∉ P with parent t, the cut X returned by the oracle is uncrossed with the sides,
away from t, of the parent edges at t (IsMinCutBetween.union, IsMinCutBetween.sdiff). This
gives a minimum s–t cut U that agrees with X on the vertices the algorithm inspects and
that no other parent pointer crosses. A re-hung vertex i keeps its label: a minimum i–t cut
missing s is a minimum i–s cut when some minimum s–t cut contains i. In the swap case,
s inherits the label of t and t gets Uᶜ; otherwise s gets U. Once every vertex is
processed, the parent graph is connected with n - 1 edges, hence a tree, and by
edgeSide_eq_of_forall_adj the side of each parent edge (u, p u) containing u is S u.
Main definitions #
Cslib.Algorithms.Lean.GomoryHu.gusfieldStep,Cslib.Algorithms.Lean.GomoryHu.gusfieldLoop,Cslib.Algorithms.Lean.GomoryHu.gusfieldParent: Gusfield's algorithm on parent functions, with a cut oracleC : V → V → Finset V.Cslib.Algorithms.Lean.GomoryHu.gusfieldStepWeight,Cslib.Algorithms.Lean.GomoryHu.gusfieldWeightLoop,Cslib.Algorithms.Lean.GomoryHu.gusfieldWithWeights: the same algorithm tracking the cut valuew u = f (S u)alongside the parent function, given a value oracleval : V → V → β.
The tree of the output is its parent graph SimpleGraph.parentGraph
(CslibFrontier.Foundations.Combinatorics.SimpleGraph.Acyclic).
Main results #
Cslib.Algorithms.Lean.GomoryHu.isGomoryHuTree_gusfieldParent: for a symmetric submodularfand an oracle returning minimum cuts, Gusfield's algorithm computes a Gomory–Hu tree off.Cslib.Algorithms.Lean.GomoryHu.gusfieldWithWeights_spec,Cslib.Algorithms.Lean.GomoryHu.isGomoryHuTree_gusfieldWithWeights,Cslib.Algorithms.Lean.GomoryHu.gusfieldWithWeights_weight_eq,Cslib.Algorithms.Lean.GomoryHu.isMinCutBetween_gusfieldWithWeights_edgeSide:gusfieldWithWeightscomputes the same Gomory–Hu tree together withw u = f (edgeSide (parentGraph p) u (p u))for every non-rootu.
References #
Iterated uncrossing #
Gusfield's algorithm #
One step of Gusfield's algorithm ([Gus90]) on the parent function p: given the
vertex s with current parent t = p s and an s–t cut X ∋ s, every other vertex with
parent t on the s-side of X is re-hung below s; if moreover the parent of t lies on the
s-side, s takes the place of t (p s := p t, p t := s).
Instances For
Gusfield's algorithm: process the vertices of l in order (skipping the root r), each
with one call C s (p s) of the cut oracle.
Instances For
The parent function computed by Gusfield's algorithm with cut oracle C, root r and vertex
order l, starting from the star centred at r.
Instances For
One step of Gusfield's algorithm on the edge-weight function w, updating edge weights from the
cut value v for (s, p s). On a swap (p (p s) ∈ X), s inherits w (p s) and p s receives
v; otherwise s receives v.
Instances For
Gusfield's loop tracking both the parent function p and edge-weight function w, using cut
oracle C and cut-value oracle val.
Instances For
The parent and weight functions computed by Gusfield's algorithm with cut oracle C, value
oracle val, root r, initial weight w₀, and vertex order l.
Instances For
Ignoring edge weights, gusfieldWeightLoop computes the same parent function as
gusfieldLoop.
The first component of gusfieldWithWeights equals gusfieldParent.
The invariant #
The step #
The processed tree edges at t #
Correctness #
Correctness of Gusfield's algorithm ([Gus90]). For a symmetric submodular f, a
cut oracle C returning a minimum s–t cut for all s ≠ t, a root r and a duplicate-free
list l containing every vertex other than r, the parent function computed by Gusfield's
algorithm is a Gomory–Hu tree of f.
Bundled correctness of Gusfield's algorithm with edge weights ([Gus90]): for a
symmetric submodular f, cut oracle C, consistent value oracle val s t = f (C s t), root r,
initial weight w₀ and duplicate-free list l covering V \ {r}, gusfieldWithWeights produces
a Gomory–Hu parent graph with fixed root r, root weight w₀, and non-root weights equal to f
on each tree-edge side.
Correctness of Gusfield's algorithm with edge weights ([Gus90]): for a symmetric
submodular f, a cut oracle C returning minimum cuts, a root r and a duplicate-free list l
covering V \ {r}, the parent component of gusfieldWithWeights is a Gomory–Hu tree of f.
For every non-root vertex u, the tree-edge side containing u in gusfieldWithWeights is a
minimum u–p u cut of f.
Edge-weight correctness of Gusfield's algorithm ([Gus90]): for every non-root vertex
u, the weight recorded by gusfieldWithWeights equals f on the tree-edge side containing
u.
The root r remains its own parent in gusfieldWithWeights.
The weight recorded at the root r in gusfieldWithWeights equals the initial weight w₀.