Algorithm Search⌘K

Proofs: Holm-de Lichtenberg-Thorup algorithm

These are the human proofs of Holm-de Lichtenberg-Thorup algorithm, at full length.

The Holm-de Lichtenberg-Thorup algorithm keeps a spanning forest full

This proof shows: correctness.

We prove that after every operation F0F_0 is a spanning forest of the current graph GG, so that line L12 answers correctly. We prove it together with the invariants of the page. Write GiG_i for the graph of edges of level at least ii, FF for the set of tree edges, and Fi=F∩GiF_i = F \cap G_i.

  • (I0) FF is a forest, every edge of FF is an edge of GG, and F0=FF_0 = F.
  • (I1) For every non-tree edge ff of level jj, the ends of ff are connected in FjF_j.
  • (I2) Every tree of FiF_i has at most n/2in / 2^i vertices.

We first show that (I0) and (I1) are enough for the claim.

Lemma 1. If (I0) and (I1) hold, then for every ii, FiF_i is a spanning forest of GiG_i, and in particular F0F_0 is a spanning forest of GG.

Proof. Fi⊆GiF_i \subseteq G_i and FiF_i is a forest by (I0). Every edge of GiG_i is either in FiF_i or a non-tree edge of level j≥ij \ge i, whose ends are connected in Fj⊆FiF_j \subseteq F_i by (I1). So every edge of GiG_i has its ends in one tree of FiF_i, and FiF_i has the same components as GiG_i. □\square

So it suffices to prove that every operation keeps (I0), (I1) and (I2). They hold for the empty graph.

Lemma 2 (insertion). INSERT keeps (I0), (I1) and (I2).

Proof. If uu and vv are in different trees of F0F_0, line L2 adds {u,v}\{u, v\} at level 0. Then FF stays a forest, and only F0F_0 changes. Its new tree joins two trees, but (I2) at level 0 only asks for at most nn vertices. Non-tree edges keep their levels and their paths in FjF_j only grow. Otherwise {u,v}\{u, v\} is a non-tree edge of level 0 whose ends are connected in F0F_0, so (I1) holds for it, and the forests do not change. □\square

Lemma 3 (deleting a non-tree edge). Line L3 keeps the invariants.

Proof. The forests do not change, and (I1) is a statement about each remaining non-tree edge separately. □\square

Now let e={u,v}e = \{u, v\} be a tree edge of level ℓ\ell that is deleted. Line L4 removes ee from FF, so FjF_j loses ee for j≤ℓj \le \ell and is unchanged for j>ℓj > \ell. For each i≤ℓi \le \ell let AiA_i and BiB_i be the trees of Fi−eF_i - e that contain uu and vv; they are the two halves of the tree of FiF_i that contained ee.

Lemma 4. Before the search, (I0) and (I2) hold, and (I1) holds for every non-tree edge except possibly those whose ends lie in different halves AjA_j and BjB_j at their level j≤ℓj \le \ell.

Proof. Removing an edge keeps a forest a forest and makes trees smaller. A non-tree edge ff of level jj had its ends connected in FjF_j. If j>ℓj > \ell, then FjF_j did not change. If j≤ℓj \le \ell and the path in FjF_j between the ends of ff did not use ee, it is still there. If it used ee, the ends of ff lie one in AjA_j and one in BjB_j. □\square

Call a non-tree edge crossing at level jj if it has level jj and its ends are one in AjA_j and one in BjB_j. Note that Aj⊆Aj−1A_j \subseteq A_{j-1} and Bj⊆Bj−1B_j \subseteq B_{j-1}, since Fj⊆Fj−1F_j \subseteq F_{j-1}.

Lemma 5 (the loop at level ii). Suppose the loop of lines L5 to L10 starts level ii and, at that moment, (I0) and (I2) hold, (I1) holds for every non-tree edge of level greater than ii, and there is no crossing edge at any level greater than ii. Then either the iteration ends at line L9 with all invariants restored, or it ends with no crossing edge at level ii, (I0) and (I2) hold, and (I1) holds for every non-tree edge of level at least ii.

Proof. Line L6 names TuT_u and TvT_v, which are AiA_i and BiB_i in some order; relabel so that TuT_u is the smaller. Since Tu∪TvT_u \cup T_v is the vertex set of one tree of FiF_i before the cut, (I2) gives ∣Tu∣+∣Tv∣≤n/2i|T_u| + |T_v| \le n / 2^i, so ∣Tu∣≤n/2i+1|T_u| \le n / 2^{i+1}.

Line L7. The tree edges of level ii in TuT_u rise to level i+1i + 1 and are linked in Fi+1F_{i+1}. All edges of TuT_u now have level at least i+1i + 1, so TuT_u is a single tree of Fi+1F_{i+1}, made of the trees of Fi+1F_{i+1} inside TuT_u joined by the raised edges. It has at most n/2i+1n / 2^{i+1} vertices, so (I2) holds at level i+1i + 1. Other trees of Fi+1F_{i+1} are unchanged. FF itself does not change, so (I0) holds. Raising tree edges only adds edges to Fi+1F_{i+1}, so (I1) still holds for every edge for which it held.

Lines L8 to L10. Take a non-tree edge ff of level ii with an end xx in TuT_u and let yy be the other end. If ff is not crossing at level ii, then by Lemma 4 its ends are connected in Fi−eF_i - e, so y∈Tuy \in T_u. If ff is crossing, then y∈Tvy \in T_v. So the test of line L9 is true exactly for crossing edges.

If y∈Tuy \in T_u, line L10 raises ff to level i+1i + 1. Its ends are in TuT_u, which is a tree of Fi+1F_{i+1}, so (I1) holds for ff. Nothing else changes.

If y∈Tvy \in T_v, line L9 makes ff a tree edge of level ii and links it in F0,…,FiF_0, \ldots, F_i. Then FF stays a forest, because ff joins A0⊇TuA_0 \supseteq T_u and B0⊇TvB_0 \supseteq T_v (in some order), which are different trees of F0−eF_0 - e. So (I0) holds. For (I2), FjF_j changes only for j≤ij \le i, where its tree Aj∪BjA_j \cup B_j is joined again by ff; this tree has vertex set equal to that of the tree of FjF_j that held ee, which had at most n/2jn / 2^j vertices. For (I1), take any non-tree edge gg of level jj. If j>ij > i, (I1) held by assumption or by the steps above. If j≤ij \le i, then in FjF_j the halves AjA_j and BjB_j are joined again by ff, and every other tree of FjF_j is unchanged, so the ends of gg, which were in one tree of FjF_j before ee was cut, are in one tree again. So all invariants hold, and the deletion ends.

If the scan ends without line L9, every non-tree edge of level ii with an end in TuT_u has been raised, so no crossing edge of level ii is left; one crossing at level ii would have an end in TuT_u and would have been found. Every remaining non-tree edge of level ii is not crossing, so (I1) holds for it by Lemma 4, and the raised edges satisfy (I1) as shown. □\square

Lemma 6. A non-tree edge of level j>ℓj > \ell is never crossing.

Proof. Its level is greater than the level of ee, so FjF_j did not contain ee, and by (I1) before the deletion its ends are connected in Fj⊆Fi−eF_j \subseteq F_i - e for every i≤ℓi \le \ell, so they lie in one tree of Fi−eF_i - e. Raising edges during the search moves edges to level at most ℓ+1\ell + 1 with both ends in one tree of Fℓ+1F_{\ell+1}, so this stays true. □\square

Theorem. After every operation, (I0), (I1) and (I2) hold, so F0F_0 is a spanning forest of GG and CONNECTED is correct.

Proof. By induction on the operations. Insertions and deletions of non-tree edges are Lemmas 2 and 3. For the deletion of a tree edge ee of level ℓ\ell, Lemmas 4 and 6 give the assumption of Lemma 5 at i=ℓi = \ell, and each iteration of Lemma 5 that does not return gives the assumption for i−1i - 1. If some iteration returns at line L9, the invariants hold. Otherwise, after level 0, there is no crossing edge at any level, (I0) and (I2) hold, and (I1) holds for every non-tree edge. In that case no edge of GG joins A0A_0 and B0B_0: tree edges do not, since A0A_0 and B0B_0 are different trees of FF, and a non-tree edge of level jj has its ends connected in Fj⊆F0F_j \subseteq F_0 by (I1), so both ends lie in one tree of F0F_0. So the component of ee is split in GG as in F0F_0 (line L11). By Lemma 1, F0F_0 is a spanning forest of GG, and uu and vv are connected in GG exactly when they are in one tree of F0F_0. ■\blacksquare

Back to Holm-de Lichtenberg-Thorup algorithm