# Batch Tree-Path Maxima and Minimum Spanning Tree Verification

[Authoritative PDF](paper.pdf) · Markdown reading copy

Sariel Har-Peled[∗](#sariel-thanks)

<a id="sariel-thanks"></a>∗School of Computing and Data Science; University of Illinois; 201 N. Goodwin Avenue; Urbana, IL, 61801, USA; [sariel@illinois.edu](mailto:spam@illinois.edu); [http://sarielhp.org/](http://sarielhp.org/). Work on this paper was partially supported by NSF AF award CCF-2317241.

### **Abstract**

We present a somewhat simpler algorithm for MST verification. It runs in linear time in expectation.

<div style="display:none">
\(
\newcommand{w}[1]{w_{#1}^{}}
\newcommand{\Set}[2]{\left\{ #1 \;\middle\vert\; #2 \right\}}
\newcommand{\textnormal{\textsc{LastTrue}}}{\textnormal{\textsc{LastTrue}}}
\newcommand{\operatorname{Low}}{\operatorname{Low}}
\newcommand{\operatorname{\mathrm{lsb}}}{\operatorname{\mathrm{lsb}}}
\newcommand{\operatorname{mask}}{\operatorname{mask}}
\newcommand{\mathcal{Q}}{\mathcal{Q}}
\newcommand{\mathbin{\gg}}{\mathbin{\gg}}
\newcommand{\operatorname{succ}}{\operatorname{succ}}
\newcommand{\operatorname{suffix}}{\operatorname{suffix}}
\)
</div>

<section id="n-3d40749a69ac2b1942e289c0b0cd2133ae3d77adf03f8aa32d89792854911122">

<a id="n-bf49119253c982890eb756ea5c2f8a9bd7cdab8c10e8415565e4a734cbb5bbce"></a>

## 1  Introduction

<a id="n-ca7c3f36ae0cb644a8e6ffb057288babc02704a17f1c94b876f00a908bc11050"></a>

Given a weighted tree and a batch of vertex pairs, the tree-path-maxima problem asks for the maximum edge weight on each corresponding tree path. Minimum spanning tree (MST) verification is an application: compare each non-tree, non-loop edge with the maximum weight on its path in the proposed tree. We describe a randomized variant of an existing linear-time framework, with the aim of reducing the machinery needed for query processing.

<a id="n-7374c6ca519fd6176895ca3a57079b10dacf1c95f981ad4e8744761185829f2a"></a>

**Approach and relation to previous work.** King \[[Kin97](#n-60f1c429739a141002db4aada6c12b421055343994ffb3fbe6f9bc774f8b4f7a)\] reduces the problem to ancestor–descendant queries in a balanced hierarchy, using Borůvka’s construction and lowest common ancestor (LCA) preprocessing. Hagerup \[[Hag10](#n-6908dd2e5463c76c1facc0b67fe9c179711bc217056abd2dcadcb779e71f83df)\] gives a deterministic linear-time algorithm for these queries, maintaining query-dependent sets of suffix maxima. His algorithm uses a set-projection operation and binary searches supported by a table of medians of bit masks. Zwick \[[Zwi09](#n-e75eb0bf3c6397d022bfc5ade1b54af6ea0d707afd9a99a6b51a61aef1c86fb3)\] presents the King–Hagerup algorithm with a direct invariant on the current answers, which is also the form of our correctness argument, and realizes the projection and the median search by table lookup on word fragments. We retain the hierarchy and LCA reduction, but allow candidate sets to contain edges that represent no current query. This permits an update that keeps a prefix of the old candidates and appends the new edge, without set projection. A sampled scan followed by a correction scan finds the update boundary, replacing median searches and their table in the query-processing stage. The analysis uses a geometric-tail bound for the correction scan and a count of queries and nodes at each height.

<a id="n-4398683f1ad19935ce925eb4bf03223f4864607b047a2a0d8cdd7c16594f81e9"></a>

**Scope and limitations.** The result returns all requested path maxima exactly and has expected linear running time. Hagerup’s bound is deterministic and holds in the worst case, so the change trades that guarantee for the stated reductions in machinery. It gives no asymptotic improvement in time or space. The simplification concerns the query-processing stage: the hierarchy construction remains, and LCA preprocessing is used as a black box. Some of the shorter proof arguments can also be used to explain earlier algorithms. The comparison therefore concerns both the algorithm and its presentation, and establishes neither a practical speed advantage nor a ranking among all approaches. The theorem assumes distinct edge weights and the word-RAM operations specified below.

<a id="n-5c681d361f718c8a01776511cdfbdef36d0c37269983e9d3e61b91f93bc447be"></a>

**AI provenance.** This work was carried out by AI assistants through OpenAI Codex under human direction. The assistants developed the algorithmic variant within the cited framework, drafted and revised the proofs, wrote implementations, and prepared this manuscript. Human input supplied the research questions, mathematical suggestions, and critical feedback that guided the work. This manuscript is presented as an AI-generated research draft.

<a id="n-6ed503eb7727ee83e71796f5de77c856532e161d2cb64b6622cf0dd2a9ce210a"></a>

**Problem and output.** Throughout, assume $n>1$ and, for simplicity of exposition, that the input edge weights are pairwise distinct.

<section id="n-aa850383ec5969008942f69814642a5596866a43a00cd1a5acf3109a94f5c9c8">

<a id="n-52129167e7d0bd0f9c78414db22ecf1994473897270e85b4f08bfe23be2693d6"></a>

**Definition 1.1.** Let $T=(V,E_T)$ be an undirected tree on $n>1$ vertices, with pairwise distinct finite real edge weights $w:E_T\to\mathbb{R}$. For distinct vertices $u,v$, let $P_T(u,v)$ denote their unique tree path and define its ***path maximum*** by

<a id="n-ccdfb0c1958e161b90811c2cec41eb26787e856806cb869d5a94ed2440205bf6"></a>



$$
w_{T}^{}(u,v)=\max\left\{ \bigl.w(e) \;\middle\vert\; e\in P_T(u,v) \right\}.
$$



<a id="n-b6343dbd841b8ed4ce8ab9a83fef2bf8f7be20f4f5d5036c253dc2d9b894f647"></a>

A ***batch of path queries*** is an indexed list $\mathcal{Q}=\bigl((u_i,v_i)\bigr)_{i=1}^{s}$ of pairs with $u_i\ne v_i$. Repeated pairs are allowed. The output is $w_{T}^{}(u_i,v_i)$, for $i=1,\ldots,s$.

</section>

<section id="n-42d654e8b09c3a71e2f28f5ad0d9d9e8bcc8761d3580b311922c781e0d6a81c2">

<a id="n-868536ca9463853e940380f5ca8bee57cda7c35608c891925caf9c044284ad7b"></a>

**Problem 1.2.** *The input is a connected, undirected graph* $G=(V,E)$*, with* $n>1$ *vertices,* $m$ *edges with pairwise distinct finite real weights, and a list of edges specifying a proposed tree* $T$*. Parallel edges and loops are allowed. A* spanning tree *connects all vertices without cycles. It is a* minimum spanning tree *if its total edge weight is smallest among all spanning trees of* $G$*.*

<a id="n-2f99f34fc05405fafe257c8d5ee3cfbbdac54a76b53d240cdca143c5f5859695"></a>

*The output first states whether* $T$ *is a spanning tree. If it is, then for every non-loop edge* $e=uv$ *the output contains* $w_{T}^{}(u,v)$ *and its* edge classification*:* $w(e)<w_{T}^{}(u,v)$*,* $w(e)=w_{T}^{}(u,v)$*, or* $w(e)>w_{T}^{}(u,v)$*. Equality holds exactly for tree edges; every other non-loop edge is lighter or heavier than its path maximum. The output also states whether* $T$ *is minimum. An edge* $e$ *with* $w(e)<w_{T}^{}(u,v)$ *is a* **violating** *edge.*

</section>

<a id="n-49ba4755b8bddbdaabd2f78397df3d2bf810781e670abbd335b35ed2cf607a82"></a>

If $T$ is not spanning, the algorithm reports it and exits.

<a id="n-8cd9c7bb7ba0cb0414afc52c8082c43e39a154e6c50eb7815ace5cf7f34f6420"></a>

**Computational model and main result.** The bounds use a word RAM with word length $W=\Theta(\log(n+s))$ for batch queries and $W=\Theta(\log(n+m))$ for MST verification. Array access, integer arithmetic on these words, Boolean operations, shifts, and finding the first or last set bit take constant time. The random source supplies independent uniform words in constant time. Edge weights are atomic values that can be copied and compared in constant time. In particular, the algorithm does not sort them or use arithmetic on them. All logarithms are in base two.

<a id="n-0d055809cac7912bb22786b3b7040cad70f0c1092f19e805235bb93f23a6a0b4"></a>

Under this model, we answer all $s$ path queries exactly in expected $O(n+s)$ time and $O(n+s)$ space, using $O(\log n)$ random words. This gives MST verification in expected $O(n+m)$ time and $O(n+m)$ space; see Theorem 6.2.

<a id="n-626acfca8f21406dcce117e862a65bb8f2829cc9a712e1c3049d366c44fb80f7"></a>

**Sketch of algorithm.** Four stages make the bound possible.

<a id="n-b8a24aadae11ddd181d11f0e06953d0bb3b5d089eadbf3550cebc6da344c8f91"></a>

(A) Build a shallow weighted hierarchy whose leaves are the vertices of $T$ and whose leaf-to-leaf path maxima agree with those of $T$ (Section 3).

<a id="n-7e6239f033c0c5fdc5ca6e6b0af33818844155bd55e4419cecf07d3205c728d9"></a>

(B) Preprocess the hierarchy for lowest common ancestor queries. Split each queried path at its lowest common ancestor into two ancestor–leaf queries (Section 4).

<a id="n-f400c06e23ffe24cd430adec660a53af692ea3f52b4c894e3db19284860ba03b"></a>

(C) Collect the query depths by a bottom-up union and prepare shared samples, choosing the sample density from each node’s height (Section 5).

<a id="n-9be8f6b4d96c6c094d3df3c3684f1a15f9597073590f4513932d851e5a97f70f"></a>

(D) Traverse downward, updating candidates with the two-scan search from Section 2, and answer queries at the leaves. Geometrically fewer nodes at larger heights pay for longer correction scans (Section 6).

</section>

<section id="n-53e1188dc97e6fa60d0734c049544922af78ebc07cc347865e5fbbc91b7eed22">

<a id="n-a83b6e5ec065925f21be89f38bab16d66c5e1d743c5ffd84fcfd7f01af3cdb11"></a>

## 2  Preliminaries

<section id="n-11ac407e22fe58a8dc3399c4fe036d47e72e112d83332bda643fefd98a115568">

<a id="n-3cfb67331615bd7690aa459bec4645fe8f247088dac7eb3c6359ba7e05f7e010"></a>

## 2  1. Small integer sets

<a id="n-73953461a10b45bd2a9afc694739d47953d14560360d9d410f544de3fe3dec27"></a>

For an integer $k\geq 0$, write $[k]=\{1,\ldots,k\}$, with $[0]=\varnothing$. A set $S\subseteq\{0,\ldots,b\}$, where $b=O(\log n)$, is represented by its ***mask*** $\operatorname{mask}(S)=\sum_{t\in S}2^t$, using $O(1)$ words. We identify sets with their masks: $\cup$ and $\cap$ are implemented by bitwise OR and AND, respectively. Write $\operatorname{Low}(t)=2^t-1$ for the mask of positions $0,\ldots,t-1$.

<a id="n-1cd8109b7c99fd733752e68a850aa48b40936dc7a77e5b582a1ad3f1ce1c2336"></a>

For a set $S$ and a nonnegative integer $q$, define its strict successor by

<a id="n-5df9b1315886b98027cd93ec5f3433e0c834151205133e70f58e8823b0d6d45c"></a>



$$
\operatorname{succ}(S,q)=\min\left\{ t\in S \;\middle\vert\; t>q \right\},
$$



<a id="n-7de2d00ba016a95afb3a86a7dffb55b108e2c47e92c94cf242abd7edb9c689ab"></a>

with value $\mathrm{⊥}$ if there is none. To compute it, shift the mask right by $q+1$ bits, setting $Y=S\mathbin{\gg}(q+1)$: return $\mathrm{⊥}$ if $Y=0$, and otherwise return $q+1+\operatorname{\mathrm{lsb}}(Y)$, where $\operatorname{\mathrm{lsb}}$ is the zero-based index of the lowest set bit. An increasing scan repeatedly extracts the lowest set bit and clears it by $Y\leftarrow Y-2^{\operatorname{\mathrm{lsb}}(Y)}$. These operations take constant time per lookup or scanned position.

</section>

<section id="n-9fd058d11699c8461df1df2154f9a106ed070288a92e7661713ff80aff75ff56">

<a id="n-f5ddbe17d663d958cb1a8613f4e478dc89a91e923495891f7cdf3256b33a11d1"></a>

## 2  2. The two-scan search

<a id="n-bb4495a31cfcdb1a0a75123a1029278f69010b703b0609ca0cafc06452d809c8"></a>

For a sorted set $D$ of nonnegative integers represented by a mask, a sample mask $R$, and a predicate $P$ true on a prefix of $D$, let <math id='n-20093df57cc8b5b923086be6cca338fd480784a4842abd27625c5690af6f6a43' xmlns='http://www.w3.org/1998/Math/MathML'><mpadded depth='0.000000pt' height='7.514986pt' width='53.265480pt'><mrow><mpadded depth='0pt' height='0pt' lspace='0.000000pt' voffset='0.000000pt' width='0pt'><mtext>L</mtext></mpadded><mpadded depth='0pt' height='0pt' lspace='7.454164pt' voffset='0.000000pt' width='0pt'><mtext>a</mtext></mpadded><mpadded depth='0pt' height='0pt' lspace='14.144696pt' voffset='0.000000pt' width='0pt'><mtext>s</mtext></mpadded><mpadded depth='0pt' height='0pt' lspace='19.138862pt' voffset='0.000000pt' width='0pt'><mtext>t</mtext></mpadded><mpadded depth='0pt' height='0pt' lspace='25.587214pt' voffset='0.000000pt' width='0pt'><mtext>T</mtext></mpadded><mpadded depth='0pt' height='0pt' lspace='34.162829pt' voffset='0.000000pt' width='0pt'><mtext>r</mtext></mpadded><mpadded depth='0pt' height='0pt' lspace='40.489856pt' voffset='0.000000pt' width='0pt'><mtext>u</mtext></mpadded><mpadded depth='0pt' height='0pt' lspace='47.180389pt' voffset='0.000000pt' width='0pt'><mtext>e</mtext></mpadded></mrow></mpadded><mo lspace='0' rspace='0' stretchy='false'>(</mo><mi>𝐷</mi><mo lspace='0' rspace='0.167em'>,</mo><mi>𝑅</mi><mo lspace='0' rspace='0.167em'>,</mo><mi>𝑃</mi><mo lspace='0' rspace='0' stretchy='false'>)</mo></math> denote the procedure that returns the largest $q\in D$ for which $P(q)$ is true, or $-1$ if none exists, using $R$ to guide the search. To implement it, scan $D\cap R$ in increasing order until the first false value or exhaustion, then scan $D$ starting immediately after the last true sampled position (or from the beginning if none was found). Stop at the first false value or exhaustion, and return the last true position found, or $-1$ if none exists.

<section id="n-62d6aa0efb88d1e878308b1af7869dcd33a83eaf0e95e3fbb2e08fc7b35367b1">

<a id="n-1c8f3f6fc0b2b68c4b470aba230b197b1f127a6bcae2d8a14917aa4d91093ec2"></a>

**Lemma 2.1.** *For every sample* $R$*,* <math id='n-ce3e9e66243e91b1585d54c6d161bab0862d95a54fd313bc0e9653656b778d2b' xmlns='http://www.w3.org/1998/Math/MathML'><mpadded depth='0.000000pt' height='7.514986pt' width='53.265480pt'><mrow><mpadded depth='0pt' height='0pt' lspace='0.000000pt' voffset='0.000000pt' width='0pt'><mtext>L</mtext></mpadded><mpadded depth='0pt' height='0pt' lspace='7.454164pt' voffset='0.000000pt' width='0pt'><mtext>a</mtext></mpadded><mpadded depth='0pt' height='0pt' lspace='14.144696pt' voffset='0.000000pt' width='0pt'><mtext>s</mtext></mpadded><mpadded depth='0pt' height='0pt' lspace='19.138862pt' voffset='0.000000pt' width='0pt'><mtext>t</mtext></mpadded><mpadded depth='0pt' height='0pt' lspace='25.587214pt' voffset='0.000000pt' width='0pt'><mtext>T</mtext></mpadded><mpadded depth='0pt' height='0pt' lspace='34.162829pt' voffset='0.000000pt' width='0pt'><mtext>r</mtext></mpadded><mpadded depth='0pt' height='0pt' lspace='40.489856pt' voffset='0.000000pt' width='0pt'><mtext>u</mtext></mpadded><mpadded depth='0pt' height='0pt' lspace='47.180389pt' voffset='0.000000pt' width='0pt'><mtext>e</mtext></mpadded></mrow></mpadded><mo lspace='0' rspace='0' stretchy='false'>(</mo><mi>𝐷</mi><mo lspace='0' rspace='0.167em'>,</mo><mi>𝑅</mi><mo lspace='0' rspace='0.167em'>,</mo><mi>𝑃</mi><mo lspace='0' rspace='0' stretchy='false'>)</mo></math> *returns the last position of* $D$ *satisfying* $P$*, or* $-1$ *if none does. If* $|D|=k$ *and each position is sampled independently with probability* $\rho>0$*, it makes at most* $k\rho+1/\rho$ *predicate evaluations in expectation and, for constant-time predicate evaluations, takes expected* $O(1+k\rho+1/\rho)$ *time.*

</section>

<section id="n-94861f3dd8099b01e76198efa5f5f9511bfbf5c9ad57c956d2b3fe80e855f3cd">

<a id="n-0da00fc6fe02aee14388c97f0f72a42d7d7a4343d089ec1fce05c64c1dd70e16"></a>

 *Proof.* The two scans find the exact boundary for every sample, and the first examines at most $k\rho$ positions in expectation. The second examines a trailing run of unsampled true positions, whose length is a truncated geometric failure count with mean at most $(1-\rho)/\rho$, plus at most one false position, giving at most $1/\rho$ expected evaluations and the claimed cost. □

</section>

</section>

</section>

<section id="n-6410f52ee4c7533522848c962ff059cca5c74e94c8ca2d1563a4ab262f512bfb">

<a id="n-167a201d3d119a929bcdb69d3ccf1bcf73ac690eb8811c85be9197caf214a6af"></a>

## 3  A balanced hierarchy preserving path maxima

<a id="n-056906fdd31ef0ea656fc16d9c3fdbb123c8159c1aa50aabf8a7ff24a7ee7333"></a>

We build a balanced hierarchy $H$ whose leaves are the vertices of the input tree $T$.

<section id="n-d4157c54dd341e23bd43ffc144b89625265cac352253302b20a3a684381498e7">

<a id="n-7ce9abc3aa52e3772512c328e0b0c8a053befebbe72db6f84a8571c31f933ad5"></a>

**Definition 3.1.** A ***balanced hierarchy*** is a rooted tree $H$ in which every internal vertex has at least two children and all leaves have the same depth $h$. For a vertex $v$, write $d_v$ for its depth, with the root at depth zero, and $h_v=h-d_v$ for its ***height***, the height of its subtree $H_v$.

</section>

<a id="n-75e9136467d14d59cc13de2f30edbd6ca0663b13cc63a1c7acfa43e47453a45c"></a>

**Construction.** The edges of $H$ are undirected. For a non-root vertex $v$, its ***parent edge*** is the edge joining $v$ to its parent. References to going up or down the tree describe movement toward or away from the root, respectively.

<a id="n-b18f75989f2288c4ad54b0b9890fd92535858711bd23cf48e4d0a843f5e437db"></a>

Initialize the current tree to be a copy of $T$, with each vertex forming a component represented by a leaf of $H$. Repeat the following Borůvka round until only one current vertex remains.

<a id="n-67a8233d99eb0ffdf7e38bac304c74508f6cdc7254c331f2cd90ec851e6527d4"></a>

(A) Each current vertex $C$ chooses its unique minimum-weight incident edge. Let $F$ be the set of chosen edges.

<a id="n-afc090ff6e41b64aa2ab86a838707e5676f9a6a5dce8766414901c0685f3e4e0"></a>

(B) Find the connected components of the forest consisting of $F$. For each such component, create a new hierarchy vertex whose children are its current vertices. If a current vertex $C$ chose edge $e_C$, give the hierarchy edge from $C$ to its new parent the original weight $w(e_C)$.

<a id="n-445326764b62abcc1c35663fc461473b25943f4528100761d7f30a5546c6ed95"></a>

(C) Contract each component of $F$ in the current tree into a node. Keep the surviving edges with their original weights, and number the new current vertices consecutively.

<a id="n-162532428c8b3a5bc1ed77c42cab87ab7e923ace0f2afaa7b0409fedef79f750"></a>

See Figure 3.1 for an example of one component of $F$.

<figure id="n-bea678beb9dfb5626d904e12c8e8c8ea5be750eef08b4be64b5687af83b45a47">

<a id="n-4584894eec660fa7f50ca79f8340302e7421fc8d0227347c3dcfee28411494bd"></a>

![Source figure](assets/component.svg)

<figcaption id="n-cf1d7d5aa6c4027319c8b5d275779e4e18ef440ec3ae6295248a037fb23c973f">

<a id="n-5bca439b62795d53aba5368cc7264730127f63ac334bf7aa30b519f115a78a99"></a>

Figure 3.1: A component of $F$ (left) becomes a node $\rho$ with six children in $H$ (right). Arrows show minimum-edge choices; the two selections of $\gamma\delta$ give both $\gamma$ and $\delta$ a parent edge of weight $2$.

</figcaption>

</figure>

<a id="n-5833380bdd23a0c490df4be7327b6aa2e8e489e8859e9ada55fb33c057ca5bcc"></a>

All current vertices in a connected component of $F$ become siblings under one new parent, even if its selected edges form a long chain. Thus a round adds one hierarchy level. The degrees in the hierarchy need not be binary: its vertices may have arbitrarily many children. We use this hierarchy directly for all subsequent query processing.

<a id="n-60f60002b4528487868057ab00444f818349be32c1eb45518023e19e2f0780bb"></a>

For a non-root hierarchy vertex $v$, write $\omega(v)$ for the weight of its parent edge. A hierarchy vertex represents a connected set of original vertices, namely its descendant leaves. An original edge selected in a round is contracted in that round, so it cannot label edges at two hierarchy levels. Its weight can occur twice only on sibling edges, when both endpoints select it. Consequently, the weights on any root-to-leaf path in $H$ are distinct.

<section id="n-23c334dc47bce9e1b1b7e4440888efd4846226fbeaecafc1102f26210403dbe3">

<a id="n-dbb67beaa3e4b74674534d62cd076dd3b4bb60acbf9406936e9c4b24ede01ccc"></a>

**Lemma 3.2.** *The construction takes* $O(n)$ *time and space. It produces a balanced hierarchy* $H$ *with* $n$ *leaves, fewer than* $2n$ *vertices, and* $h\leq\lfloor\log n\rfloor$*. If* $N_i$ *is the number of vertices of height* $i$*, then* $N_i\leq n/2^i$*.*

</section>

<section id="n-76940876fa48ec30abbfdc981d45a42c85a1821d5d95b492e025c7e89a1b22d6">

<a id="n-f29020faec43629c5511cb9c2a6062ccf7706ae79a177a56bbd1d7136a8b0f67"></a>

 *Proof.* At any nonfinal round, the current graph is a tree with at least two vertices. Every vertex chooses an incident edge, so every component of $F$ has at least two vertices. The next tree therefore has at most half as many vertices. A round scans only the current tree: find minima, traverse $F$, and rebuild the remaining edge list in linear time in its current size. The total cost is a geometric series. Scanning the original graph or all original vertices in every round would not have this bound.

<a id="n-2c3dedc4eed4410e3a91397d13c17c58120a325c5f0a2eba45bcf63b5f3ee2a9"></a>

Each original leaf gets exactly one new ancestor per round. Hence all leaves have depth $h$, and each internal vertex has at least two children. The total number of vertices is less than $n+n/2+n/4+\cdots=2n$, and there are at most $\lfloor\log n\rfloor$ rounds. A height-$i$ vertex contains at least $2^i$ leaves. Distinct vertices at that height have disjoint leaf sets, proving the bound on $N_i$. □

</section>

<section id="n-0e63c821f3b905e1ee271158af0261e0ba55d7c72bcfe3f577022128f4875ad1">

<a id="n-b05a8c8bdac4b012318da959673bdc5af79cf24dd19a4f3bb3e0e607f3f06455"></a>

**Lemma 3.3.** *For every pair of distinct original vertices* $u,v$ *(i.e., leaves of* $H$*), the maximum weight on* $P_H(u,v)$ *is* $w_{T}^{}(u,v)$*.*

</section>

<section id="n-68d1fedb1773c902bee5354bcfbfc2362ab35005f930915d08b100699aca6c8f">

<a id="n-c0bb6e3a49a80df57f276000c985694550dcc581ad0bedf096aed4b1200c1571"></a>

 *Proof.* For one component of the selected forest $F$ in one round, let $r$ be its new hierarchy vertex and write $\omega(C)=w(e_C)$ for each cluster $C$. For distinct clusters $C,D$, let $e$ be the maximum-weight edge on their path. Since $e\in F$, one of its endpoints selected it. An internal vertex of the path cannot select $e$, because its other incident path edge is lighter. Thus $C$ or $D$ selected $e$. Each endpoint’s selected minimum is no larger than its incident path edge, so

<a id="n-3dbe780b7dd7939adae9083e40639d2ddf4c77f0091c9cd4323d3fcac665cb0b"></a>



$$
w(e)=\max\{\omega(C),\omega(D)\}.
$$



<figure id="n-dc74a09cc78ca870c31780f9b12fd147922b5451dedc450c66d3731db1f75bdf">

<a id="n-0597d4bde519f0838a82075eecc8f46620e90f2f6ecce8d4794894c07ff9643c"></a>

![Source figure](assets/flatten.svg)

<figcaption id="n-9827671cdf87f5b42318998ae3581d003004e1544c2d78fa5654473cbf5fac3f">

<a id="n-cb6a9a952c894ce4e90e85422332327a539410a9bfccaad42ed579f458f14dfb"></a>

Figure 3.2: Flattening a selected component. On the left, the mutually selected edge of weight $2$ has been split at $\rho$. On the right, each cluster attaches to $\rho$ with its selected weight, preserving all path maxima.

</figcaption>

</figure>

<a id="n-8a041394c863413b9f482e08a0dee6c177eb8fe372a307545206ed670812f452"></a>

This is exactly the maximum on the path $C,r,D$ in the replacement star, proving that flattening preserves path maxima between clusters. See Figure 3.2.

<a id="n-b9638aada8759a72a43f10a787dbdaa47d6702f7cd4f030a8fcb86c3daab3ef5"></a>

Moving a surviving edge $e$ from $C$ to $r$ leaves paths internal to $C$ unaffected. Every affected path uses $e$; since $w(e)>\omega(C)$, adding or removing the lighter edge $Cr$ leaves its maximum unchanged. Applying these rewritings round by round transforms $T$ into $H$ while preserving all path maxima between original vertices. □

</section>

</section>

<section id="n-90bc62daaf2d5149ef73074d2f6793aff2663d86b04d38a2c9a481c5ee3011c9">

<a id="n-c922ab3659d2859daae3417d1df32f1d13b64fc467c6a1afd18727cf20c5edf3"></a>

## 4  Splitting queries at lowest common ancestors

<a id="n-c74db1f4b8eddf10460a07b6b53d58baf497cb9692a570f5d359491655536bc6"></a>

Lowest common ancestor (LCA) data structures admit reasonably simple constructions, such as that of Bender and Farach-Colton \[[BF00](#n-e08fd58e713a39333f2cd5c9fb32c34c13f079cb09307df0c9b6a0215e322884)\], with linear preprocessing time and space and constant query time. We use such a structure to preprocess the hierarchy $H$. This is the only black box needed below. We work directly on $H$ throughout the rest of the algorithm. For an integer $0\leq q\leq d_v$, let $v[q]$ denote the ancestor of $v$ at depth $q$; in particular, $v[d_v]=v$. Since $h\leq\lfloor\log n\rfloor$, a set of depths can be represented by a mask of $h+1=O(\log n)$ bits.

<section id="n-9bdf1e6b2b9fb7f9d77f6ea4d0d2fc0ff0a49ec75d73726a0e9ad9c0cc83865d">

<a id="n-2ef9b832295a8203cf4e6f5ce9c223a32d35740a27c9cddc66062254e7a5798a"></a>

**Definition 4.1.** For a query $(u_i,v_i)$, let $\Delta_i$ be the depth of its LCA in $H$. Split the path at this ancestor. Each of the two ***ancestor–leaf queries*** asks for the maximum edge weight from one endpoint up to the ancestor. Store one at each endpoint, with ***query depth*** $\Delta_i$ and a reference to the original query.

</section>

<a id="n-5d199cebfc95199e0edb8f61b93ddde4bb99a7ac3da163abd5e49703cc208fb8"></a>

Only the LCA’s depth is needed after this step. There are $2s$ ancestor–leaf query records, and distinct query endpoints give $0\leq\Delta_i<h$. Computing all query depths and storing the records takes $O(s)$ time and space after preprocessing.

<section id="n-3333c6f89200e5285d1852ceb0e21a894f8cad5956f4bb7c6f25133579c29b9a">

<a id="n-7b3160ee0beb91bcd8935063b72e821a35dfead8726bfb2490da71cc107ca2a6"></a>

**Observation 4.2.** *The two ancestor–leaf queries for* $(u,v)$ *partition the edges of* $P_H(u,v)$*. Their maximum values therefore combine to* $w_{T}^{}(u,v)$*.*

</section>

</section>

<section id="n-751510ef51bd0984a7ff2e51c435d9dde1ef7e4ab4a283fdbc5993fcca1b3268">

<a id="n-d7d717148e23e94f090ac952d7a5aa511e7a7f0391ecb0342dbdb82d90ff0fc2"></a>

## 5  Answering the queries at the leaves

<a id="n-c973efe35a324132abd6b7751647a0e8cd638f9720ffd0a0a2978300b6364010"></a>

Each ancestor–leaf query is stored and answered at its endpoint leaf $v$. A record with query depth $\Delta_i$ asks for the heaviest edge on the path from $v[\Delta_i]$ to $v$. We obtain these answers by a depth-first traversal of $H$. At internal nodes, we maintain candidates for partial answers to queries at descendant leaves; reaching a leaf completes its answers.

<section id="n-1aa265eb4b48a6a8d732e4f4fe4cc3e0d5473129d16306f6bb2572a0d8194ddd">

<a id="n-9ae413865b7d4a5fbb337a5d0b0307222d7c08e7031cf8e5f17100f0e40315cf"></a>

## 5  1. Partial answers for descendant queries

<section id="n-52d81c943b7e5e67a1c70999385ba2604c9a589c6affdeb6d19d23373f0c637d">

<a id="n-85f9d18d5ba2fbf12855e44b483dc0aa3fd5ad0a9e9928f563e175d7c64eb2e5"></a>

**Definition 5.1.** For a non-root vertex $v$ of $H$, let $\Pi_v$ be the set of ancestor–leaf query paths that use the parent edge of $v$. Write $u(P)$ for the upper endpoint of a path $P\in\Pi_v$. The ***demand set*** at $v$ is

<a id="n-9b1191e389163c49a5b56722db2f96e18e0ebdd514663b34f2940dabd478f225"></a>



$$
D_v=\left\{ d_{u(P)} \;\middle\vert\; P\in\Pi_v \right\}
        \subseteq\{0,\ldots,d_v-1\}.
$$



<a id="n-7c027a35c0b11cc1068126dd5a251fa35b16af9d68a3dfe310889b224ae1a49c"></a>

Set $\Pi_r=D_r=\varnothing$ at the root $r$. For any vertex $v$ and integer $0\leq q\leq d_v$, the ***partial answer*** $\operatorname{suffix}(q,v)$ is the weight of the heaviest edge on the path from $v[q]$ to $v$. The empty path at $q=d_v$ has value $\hspace{0pt}\mathord{−}\hspace{0.222em} \mathrm{∞}$.

</section>

<a id="n-e3da5a3b72987ca31c17d5abaf961e8e47a299ef04f40c7e95e917e52f4ce6ec"></a>

At a leaf $v$, $\operatorname{suffix}(\Delta_i,v)$ answers the stored ancestor–leaf query. At an internal node, $\operatorname{suffix}(q,v)$ is the maximum over the part of that path reached so far. Candidate sets represent these values implicitly.

<a id="n-6e587da958304cde18073be275a75bd28be6666adc582781cdcddfe8c3ed2ba8"></a>

Each $q\in D_v$ identifies the upper endpoint $v[q]$. Store $D_v$ as a bit mask, with one bit per distinct depth; the sets $\Pi_v$ need not be stored. Compute the masks upward: collect query depths at leaves, and at each internal vertex $v$ take the union of its children’s masks and discard all depths at least $d_v$, by intersecting with $\operatorname{Low}(d_v)$. A path with upper endpoint $v$ contributes a demand below $v$, but does not use the parent edge of $v$. At each leaf, store all the queries associated with it.

<a id="n-53a568ac58e5b8fe555fbaf059ec9fd2736aabd03a7150a1045d2b3e71c8478e"></a>

While visiting $v$, let $\beta[t]=\omega(v[t])$ for $1\leq t\leq d_v$: this is the weight of the parent edge of $v[t]$. Adopt the lookup convention $\mathit{β} \hspace{0pt}\mathord{[}\hspace{0pt} \mathrm{⊥} \hspace{0pt}\mathord{]}\hspace{0pt} \hspace{0.278em}\mathord{=}\hspace{0pt} \hspace{0.278em}\mathord{−}\hspace{0pt} \mathrm{∞}$ for an absent successor.

<section id="n-53f2d8f1f79502cfe3b5fc853dbc67e077a13a4a10897c9e88357d82cbd079ae">

<a id="n-d0c05f8f684bbe79f714e7aab1fd3cb99f63cf042534a27ec02e6b087a3d0071"></a>

**Definition 5.2.** For a vertex $v$ of $H$, the ***candidate set*** $S_v$ contains depths of non-root nodes on the root-to-$v$ path. Each $t\in S_v$ represents the parent edge of $v[t]$. These edge weights strictly decrease as $t$ increases, and

<a id="n-4bf16b34081e0a70f5fe9515ba0512228e4735144beaa99115dbff95d5cd84c7"></a>



$$
\beta[\operatorname{succ}(S_v,q)]=\operatorname{suffix}(q,v)
        \qquad\text{for every }q\in D_v.
$$



</section>

<a id="n-0043658eaf3aa5b4686d78a858d18268b44f0ef7a37d93cbb9a3e5464aa358c5"></a>

Thus the first candidate deeper than $q$ supplies the partial answer $\operatorname{suffix}(q,v)$. At a leaf this is the requested answer. Extra candidates that represent no current demand are allowed.

</section>

<section id="n-3095990fb015931232d478326708c6d51c87d20ce0f1ea7a90beb920824d5fc4">

<a id="n-ad9898d61a0f71dec0f8cbfad1665736f194d8503f38ec0859957323d7d5ec92"></a>

## 5  2. Preparing the shared samples

<a id="n-98efe32b4f8e6e0c2e0f941b24a8f412bb694a83b15ca592bc19ceca4a09ac7b"></a>

Let $R_0$ contain all positions $0,\ldots,h$. For $j=0,\ldots,\lfloor h/2\rfloor-1$, draw a mask $U_j$ whose bits are independent fair coin flips, independently of all previous draws, and set $R_{j+1}=R_j\cap U_j$. Prepare these masks before the traversal. A node $v$ of height $h_v$ uses the sample $R_{\lfloor h_v/2\rfloor}$, so at height $i$ each position is sampled independently with probability $\rho_i=2^{-\lfloor i/2\rfloor}$. Nodes of the same height share a sample mask.

</section>

<section id="n-6bd0d42b8d87bd96b50412f9c52485594d8b8ae16dc474a9dbf8b88bd64dbe1d">

<a id="n-1a354be9d8a6985f83c303fa85a5a0099c66e64718393dcedc62b42795190e9b"></a>

## 5  3. Updating the candidates

<a id="n-8133050b174e0426a55e24914bf240305cfeed9bd5fee0abfcc8e9fe84ff3b66"></a>

Suppose a non-root node $v$ has parent $u$, depth $d_v$, and parent edge $uv$ of weight $w=\omega(v)$. Extending the current path by this edge changes the partial answers, for $q\in D_v$, according to

<a id="n-b1e497968cc3662c379a95033b0ccd616ab7484877a2de5b5b43f5303f7d6d8f"></a>



$$
\operatorname{suffix}(q,v)=\max\{\operatorname{suffix}(q,u),w\},
    \qquad q\in D_v.
$$



<a id="n-7e7e670fff37849b73ae1bc5b4e14ef41fd0621773bed34a9787de34fd293b72"></a>

To implement it, keep the shortest prefix of $S_u$ containing the candidates for all demands whose old partial answers exceed $w$, then append depth $d_v$.

<a id="n-4d7c369902a666267ac9fd43b2fe167e9dc973f675b871394ae2aca5d26f66e1"></a>

Let $S=S_u$. The predicate $P_v(q)=[\beta[\operatorname{succ}(S,q)]>w]$ is true on a prefix of $D_v$, since the old partial answers are nonincreasing as $q$ increases. Compute

<a id="n-b0b9e99e98d0ebf25d3247d3416c212d471a97aff9d5365c127e59d76bbb8ce0"></a>

<math display='block' id='n-5b7f6c4b85a5977db1dd63f1a87694403e5858e229fe880c2aa1a86f3e25117c' xmlns='http://www.w3.org/1998/Math/MathML'><msup><mi>𝑞</mi><mi mathvariant='normal'>*</mi></msup><mo lspace='0.278em' rspace='0.278em'>=</mo><mpadded depth='0.000000pt' height='7.514986pt' width='53.265480pt'><mrow><mpadded depth='0pt' height='0pt' lspace='0.000000pt' voffset='0.000000pt' width='0pt'><mtext>L</mtext></mpadded><mpadded depth='0pt' height='0pt' lspace='7.454164pt' voffset='0.000000pt' width='0pt'><mtext>a</mtext></mpadded><mpadded depth='0pt' height='0pt' lspace='14.144696pt' voffset='0.000000pt' width='0pt'><mtext>s</mtext></mpadded><mpadded depth='0pt' height='0pt' lspace='19.138862pt' voffset='0.000000pt' width='0pt'><mtext>t</mtext></mpadded><mpadded depth='0pt' height='0pt' lspace='25.587214pt' voffset='0.000000pt' width='0pt'><mtext>T</mtext></mpadded><mpadded depth='0pt' height='0pt' lspace='34.162829pt' voffset='0.000000pt' width='0pt'><mtext>r</mtext></mpadded><mpadded depth='0pt' height='0pt' lspace='40.489856pt' voffset='0.000000pt' width='0pt'><mtext>u</mtext></mpadded><mpadded depth='0pt' height='0pt' lspace='47.180389pt' voffset='0.000000pt' width='0pt'><mtext>e</mtext></mpadded></mrow></mpadded><mpadded depth='3.818156pt' height='9.272692pt' width='4.566235pt'><mpadded depth='0pt' height='0pt' lspace='0.000000pt' voffset='0.000000pt' width='0pt'><mrow><mo fence='true' lspace='0' maxsize='13.090848pt' minsize='13.090848pt' rspace='0' symmetric='true'>(</mo><mspace depth='0.000000pt' height='13.090848pt' width='0.000000pt'/><mspace width='0.000pt'/></mrow></mpadded></mpadded><msub><mi>𝐷</mi><mi>𝑣</mi></msub><mo lspace='0' rspace='0.167em'>,</mo><msub><mi>𝑅</mi><mrow><mo lspace='0' rspace='0' stretchy='false'>⌊</mo><msub><mi>ℎ</mi><mi>𝑣</mi></msub><mo lspace='0' rspace='0'>/</mo><mn>2</mn><mo lspace='0' rspace='0' stretchy='false'>⌋</mo></mrow></msub><mo lspace='0' rspace='0.167em'>,</mo><msub><mi>𝑃</mi><mi>𝑣</mi></msub><mpadded depth='3.818156pt' height='9.272692pt' width='4.566235pt'><mpadded depth='0pt' height='0pt' lspace='0.000000pt' voffset='0.000000pt' width='0pt'><mrow><mo fence='true' lspace='0' maxsize='13.090848pt' minsize='13.090848pt' rspace='0' symmetric='true'>)</mo><mspace depth='0.000000pt' height='13.090848pt' width='0.000000pt'/><mspace width='0.000pt'/></mrow></mpadded></mpadded><mo lspace='0' rspace='0'>.</mo></math>

<a id="n-168cf80fb6d4fb47ad04128869a27bb9a5cbf155a29798652753d6fd5dd08cf7"></a>

Then set

<a id="n-544d51f1631fa6913ede4574ab1b511fb33005d004accb26b6d14d94158b9ae8"></a>

<math display='block' id='n-aacf820a30ed1f9b722ee1730661f683b49d9376103d91c94a56404fd3f6e6b2' xmlns='http://www.w3.org/1998/Math/MathML'><mpadded depth='0.000000pt' height='0.000000pt' width='0.000000pt'><mrow><mpadded depth='0pt' height='0pt' lspace='0.000000pt' voffset='13.549197pt' width='0pt'><mspace depth='0.000000pt' height='0.000000pt' width='0.000000pt'/></mpadded></mrow></mpadded><mrow/><mi>𝑘</mi><mo lspace='0.278em' rspace='0.278em'>=</mo><mrow><mo fence='true' lspace='0' rspace='0' symmetric='true'>{</mo><mtable columnalign='left left'><mtr><mtd style='text-align:left'><mrow><mi mathvariant='normal'>succ</mi><mo lspace='0' rspace='0' stretchy='false'>(</mo><mi>𝑆</mi><mo lspace='0' rspace='0.167em'>,</mo><msup><mi>𝑞</mi><mi mathvariant='normal'>*</mi></msup><mo lspace='0' rspace='0' stretchy='false'>)</mo><mo lspace='0' rspace='0'>,</mo></mrow></mtd><mtd style='text-align:left'><mrow><msup><mi>𝑞</mi><mi mathvariant='normal'>*</mi></msup><mo lspace='0.278em' rspace='0'>≠</mo><mo lspace='0.278em' rspace='0'>−</mo><mn>1</mn><mo lspace='0' rspace='0'>,</mo></mrow></mtd></mtr><mtr><mtd style='text-align:left'><mrow><mn>0</mn><mo lspace='0' rspace='0'>,</mo></mrow></mtd><mtd style='text-align:left'><mrow><msup><mi>𝑞</mi><mi mathvariant='normal'>*</mi></msup><mo lspace='0.278em' rspace='0'>=</mo><mo lspace='0.278em' rspace='0'>−</mo><mn>1</mn><mo lspace='0' rspace='0'>,</mo></mrow></mtd></mtr></mtable><mspace width='1.196pt'/></mrow><mspace width='21.818pt'/><mspace width='0.167em'/><msub><mi>𝑆</mi><mi>𝑣</mi></msub><mo lspace='0.278em' rspace='0'>=</mo><mo lspace='0.278em' rspace='0' stretchy='false'>(</mo><mi>𝑆</mi><mo lspace='0.222em' rspace='0'>∩</mo><mo lspace='0.222em' rspace='0' stretchy='false'>[</mo><mi>𝑘</mi><mo lspace='0' rspace='0' stretchy='false'>]</mo><mo lspace='0' rspace='0' stretchy='false'>)</mo><mo lspace='0.222em' rspace='0'>∪</mo><mo lspace='0.222em' rspace='0' stretchy='false'>{</mo><msub><mi>𝑑</mi><mi>𝑣</mi></msub><mo lspace='0' rspace='0' stretchy='false'>}</mo><mo lspace='0' rspace='0'>.</mo></math>(5.1)

<a id="n-24a71d7b616f6a756f1475e95a0e9434c8835b9c64c3910a7fea29f06c64cef7"></a>

Position zero is never a candidate, so $k=0$ retains nothing. The intersection and union take constant time on masks, so the update takes constant time after finding ${\mathit{q}}^{\mathrm{*}}$.

<section id="n-2a943abe4c59de7dc069193db83043ad1c5e7b11cba69194ac6823417b1bc013">

<a id="n-506e6c20cd8e5d4add70ea1f3f2fa31d641e8d314229bcac0603f5fdf345a60c"></a>

**Lemma 5.3.** *Starting with the empty set at the root, these updates preserve* *Definition 5.2* *for every choice of the sample masks.*

</section>

<section id="n-8dba18d5d57fde96d7869b883c0d8e04f58f23d75cda37f88281b90217840659">

<a id="n-bfbaca9b63e0f2742b6fdee662a5e93951b57598792d2ee0d3285c452bbf196d"></a>

 *Proof.* Proceed by induction from the empty candidate set at the root. For a non-root node $v$ with parent $u$, the parent’s candidates represent the old answers for all $q\in D_v$: inherited demands satisfy the invariant, and any new demand has $q=d_u$, with both an empty partial path and no successor. By Lemma 2.1, <math id='n-305be3100c9b9a02c344180f0c46eb5a710c8b6220bb3e2a37daa1d7b50be956' xmlns='http://www.w3.org/1998/Math/MathML'><mpadded depth='0.000000pt' height='7.514986pt' width='53.265480pt'><mrow><mpadded depth='0pt' height='0pt' lspace='0.000000pt' voffset='0.000000pt' width='0pt'><mtext>L</mtext></mpadded><mpadded depth='0pt' height='0pt' lspace='7.454164pt' voffset='0.000000pt' width='0pt'><mtext>a</mtext></mpadded><mpadded depth='0pt' height='0pt' lspace='14.144696pt' voffset='0.000000pt' width='0pt'><mtext>s</mtext></mpadded><mpadded depth='0pt' height='0pt' lspace='19.138862pt' voffset='0.000000pt' width='0pt'><mtext>t</mtext></mpadded><mpadded depth='0pt' height='0pt' lspace='25.587214pt' voffset='0.000000pt' width='0pt'><mtext>T</mtext></mpadded><mpadded depth='0pt' height='0pt' lspace='34.162829pt' voffset='0.000000pt' width='0pt'><mtext>r</mtext></mpadded><mpadded depth='0pt' height='0pt' lspace='40.489856pt' voffset='0.000000pt' width='0pt'><mtext>u</mtext></mpadded><mpadded depth='0pt' height='0pt' lspace='47.180389pt' voffset='0.000000pt' width='0pt'><mtext>e</mtext></mpadded></mrow></mpadded></math> is exact, so truncating at $k$ retains the representative of every demand whose old answer exceeds $w$, and every retained candidate has weight greater than $w$. Consequently, every remaining demand has no retained successor and is represented by the appended candidate $d_v$. Thus the update takes the maximum of each old answer and $w$, while preserving strictly decreasing candidate weights. □

</section>

</section>

<section id="n-93ea017cbe752e13029bafb82baed29d89caa4b99f7fc7e6f900e8393940a3b4">

<a id="n-352ccbf6ac79876bca69f0cb6c8be50f278a649c8c9a882db4d3b7a2cb642b8a"></a>

## 5  4. Completing the answers and implementing the traversal

<a id="n-4298a6ee80af48ed57fa8df3a07b495df1a6831cea1131a3f3be7e10bb605384"></a>

Initialize ${\mathit{M}}_{\mathit{i}} \hspace{0.278em}\mathord{=}\hspace{0pt} \hspace{0.278em}\mathord{−}\hspace{0pt} \mathrm{∞}$ for each query $i$. Traverse $H$ in depth-first order, starting with the empty candidate set at the root. At each non-root node $v$, set $\beta[d_v]=\omega(v)$ and perform Eq. (5.1). At an internal node, pass the resulting candidate set by value to each child. At a leaf $v$, the partial answers are now complete: process each stored ancestor–leaf query by updating its original query’s answer:

<a id="n-5b3ee168d379be79ee93f92e7b88b4df88907b041217426a6091fe8f1e6d27a0"></a>



$$
M_i\gets\max\{M_i,\beta[\operatorname{succ}(S_v,\Delta_i)]\}.
$$



<a id="n-bc7a65804f8bf330504e7082b072e6ae3cd360860ef1dbc4bef69b5fec2650d3"></a>

Only leaves update the output values $M_i$. After the traversal, return $M_1,\ldots,M_s$. The candidate invariant and Observation 4.2 give $M_i=w_{T}^{}(u_i,v_i)$ for every choice of the sample masks, proving the correctness assertion of Theorem 6.2. Passing the set by value preserves the parent’s state for its other children. The array $\beta$ can be shared: a descendant writes only at a greater depth, and lookups use only depths on the current path.

</section>

</section>

<section id="n-31462c267a9ce77e2d3c5a3525486e79ea2075862ca8011070d9ea02d3fa82af">

<a id="n-25ea065e65bc7641da2491d858ac99baa24456057960321e8ce16e4dd9d116df"></a>

## 6  Running time and space

<section id="n-d2749990f6edd8632943e5ff77b00fc463e5c6584b6ebd86d0a6c5a97bb07bae">

<a id="n-1141b60489f532e779f2db26968ea93f0ee1a7e91a31489fe242866a3109d401"></a>

**Lemma 6.1.** *At each hierarchy height* $i$*, the sum of demand-set sizes over nodes is at most* $2s$*. Moreover,* *Lemma 2.1* *applies at every non-root vertex of height* $i$ *with* $\rho_i=2^{-\lfloor i/2\rfloor}$*, even though its sample mask is shared with other vertices and correlated with earlier work.*

</section>

<section id="n-1f97c63dc5dd4aff3f29a78001613116070a15ceae41baa09dee311f0a5bd408">

<a id="n-621c0a5a9ad1e07b96249fe3af0f6ebf9107470989c3cecf83d74c967da66399"></a>

 *Proof.* Charge a distinct demand at a height-$i$ vertex to one descendant ancestor–leaf query record having that query depth. Subtrees rooted at vertices of the same height are disjoint, so no record is charged twice. This proves the demand bound.

<a id="n-db84fb06a0aa19e426552edc9c82608478593613f468e6138ebfa74a3397bb07"></a>

For fixed $j$, a bit survives in $R_j$ exactly when it is present in $j$ independent uniform masks. Its survival probability is $2^{-j}$, and distinct bits depend on disjoint independent random bits. Therefore the required within-mask independence holds.

<a id="n-3831b4cf1e46f2633fb3599b54ebb61d868af40bb26b9f318889b7b1eaf17047"></a>

The samples affect only how <math id='n-e6d43f50812b5f25a655d355f1125598a97569697d9f8def2d60da54d70bb370' xmlns='http://www.w3.org/1998/Math/MathML'><mpadded depth='0.000000pt' height='7.514986pt' width='53.265480pt'><mrow><mpadded depth='0pt' height='0pt' lspace='0.000000pt' voffset='0.000000pt' width='0pt'><mtext>L</mtext></mpadded><mpadded depth='0pt' height='0pt' lspace='7.454164pt' voffset='0.000000pt' width='0pt'><mtext>a</mtext></mpadded><mpadded depth='0pt' height='0pt' lspace='14.144696pt' voffset='0.000000pt' width='0pt'><mtext>s</mtext></mpadded><mpadded depth='0pt' height='0pt' lspace='19.138862pt' voffset='0.000000pt' width='0pt'><mtext>t</mtext></mpadded><mpadded depth='0pt' height='0pt' lspace='25.587214pt' voffset='0.000000pt' width='0pt'><mtext>T</mtext></mpadded><mpadded depth='0pt' height='0pt' lspace='34.162829pt' voffset='0.000000pt' width='0pt'><mtext>r</mtext></mpadded><mpadded depth='0pt' height='0pt' lspace='40.489856pt' voffset='0.000000pt' width='0pt'><mtext>u</mtext></mpadded><mpadded depth='0pt' height='0pt' lspace='47.180389pt' voffset='0.000000pt' width='0pt'><mtext>e</mtext></mpadded></mrow></mpadded></math> finds the boundary, not which boundary it returns. Starting with the empty candidate set, every candidate update is therefore determined by the input, independently of the sample masks. Thus each predicate is fixed independently of its sample, and the single-search bound applies to its marginal distribution. Independence between vertices is not needed. □

</section>

<section id="n-7835b21ff5966b61457c090d6497d97d6f9c9f750257e7e4f58cac7f0df35e94">

<a id="n-ff3e44b8cd08b59287b1a2ddfc3b1fd069e22dfcfe685062b3a97bf6f2a8e4c7"></a>

**Theorem 6.2.** *Under the model of* *Section 1**, a tree with* $n$ *vertices, distinct edge weights, and a batch of* $s$ *path queries can be processed in expected* $O(n+s)$ *time and* $O(n+s)$ *space. The algorithm returns the path-maximum for all the batched queries. It uses* $O(\log n)$ *random words in total. Consequently,* *MST* *verification takes expected* $O(n+m)$ *time and* $O(n+m)$ *space.*

</section>

<section id="n-1a0879377e0e61720fef33b73645db8bd60d57c4ceecf884fdd0928679accf15">

<a id="n-d621168abcc88761e5653ab2e92b2e3b94e8fd083d39b8d8a016d3721c1f8b02"></a>

 *Proof.* Correctness was established in Section 5. We now prove the resource bounds. The root needs no search. Including it only loosens the following upper bound. By Lemma 6.1, the expected total number of search predicate evaluations is at most

<a id="n-803b164a1c41ab578647429da455c77fa49cdacd233cc8d098e1aaf5fd576833"></a>

<a id="n-da96628b5024142c0e3d072f082d270bc0c61e5f4839441fe7d3e9836a7cc148"></a>

$$
\begin{aligned}
\sum_{i=0}^{h}\left(2s\rho_i+\frac{N_i}{\rho_i}\right)
        &\leq 2s\sum_{i\geq 0}2^{-\lfloor i/2\rfloor}
        +n\sum_{i\geq 0}2^{-\lceil i/2\rceil}\\
&=8s+3n.
\end{aligned}
$$



<a id="n-22deaca2601104282a36ccaa9404104c8faf45b65fa72b02a7d89b78530e0a39"></a>

<a id="n-f5912e71457c68c220a4497210ff934179a8eca37835910b30ab0268548a75c1"></a>

<a id="n-98bd26a2e41911e67098aa34965940294765c8b5da9b31ac95d470bb2cc49536"></a>

Here $N_i\leq n/2^i$ by Lemma 3.2. Each predicate evaluation performs one successor query and at most one weight comparison. Linearity of expectation is valid despite the shared randomness.

<a id="n-aade8f74e4b874d43e7396f731b69edd0dee35acaaaab21e076a6f92d1afb916"></a>

The hierarchy and its LCA structure cost $O(n)$ time and space. Computing query depths and storing both records costs $O(s)$. Bottom-up unions, removal of depths at least the current depth, and candidate updates take constant time per hierarchy edge or vertex. Generating the sample masks takes $O(h)$ work, $O(h)$ words of storage, and $O(h)$ random words. Finally, decoding and accumulating the $2s$ ancestor–leaf answers costs $O(s)$. This accounts for all work and gives expected $O(n+s)$ total time.

<a id="n-d040dfce9fb238d5b50be597d23e20c17de9eefc710ef013fb13f20061953233"></a>

The hierarchy, LCA structure, demands, and candidate state occupy $O(n)$ words. The weight array $\beta$ and traversal stack need $O(h+1)=O(\log n)$ words; the query records and answers need $O(s)$. No scan materializes a list of its set bits. Hence the space bound is $O(n+s)$ for every random choice.

<a id="n-4621ea3bc055d9e1dfcad75fe1a8e07163294b0e09bee2976ed057bdcbf5b611"></a>

**MST verification.** First check in $O(n+m)$ time that the proposed edges form a spanning tree. For a valid proposal, query every non-tree, non-loop edge and compare its weight with its returned path maximum. This gives all lighter, equal, or heavier classifications; each tree edge has its own weight as its path maximum, and loops are marked separately. By the cycle criterion, the proposed tree is minimum exactly when no edge is lighter than its path maximum. This takes expected $O(n+m)$ time and $O(n+m)$ space. □

</section>

</section>

<section id="n-654915b385cad1d9c88d07c0e40f7638edb042e1ab351ba423fc6ac3846f2ec7">

<a id="n-b08b1527fa53e45b61a6dd9eb6ff5cc0d6f0d2293321ec6dbf3cdf0b7721a4b8"></a>

## References

<a id="n-e08fd58e713a39333f2cd5c9fb32c34c13f079cb09307df0c9b6a0215e322884"></a>

\[BF00\] Michael A. Bender and Martín Farach-Colton. “The LCA Problem Revisited”. In: *LATIN 2000: Theoretical Informatics*. Vol. 1776. Lecture Notes in Computer Science. Springer, 2000, pp. 88–94. <span style="font-variant:small-caps">doi</span>: [$10 \hspace{0.222em}\mathord{.}\hspace{0.222em} 1007 \hspace{0.222em}\mathord{/}\hspace{0.222em} 10719839 \hspace{0.222em}\mathord{\_}\hspace{0.222em} 9$](https://doi.org/10.1007/10719839_9).

<a id="n-6908dd2e5463c76c1facc0b67fe9c179711bc217056abd2dcadcb779e71f83df"></a>

\[Hag10\] Torben Hagerup. “An Even Simpler Linear-Time Algorithm for Verifying Minimum Spanning Trees”. In: *Graph-Theoretic Concepts in Computer Science*. Ed. by Christophe Paul and Michel Habib. Vol. 5911. Lecture Notes in Computer Science. WG 2009. Springer, 2010, pp. 178–189. <span style="font-variant:small-caps">doi</span>: [$10 \hspace{0.222em}\mathord{.}\hspace{0.222em} 1007 \hspace{0.222em}\mathord{/}\hspace{0.222em} 978 \hspace{0.278em}\mathord{-}\hspace{0.278em} 3 \hspace{0.278em}\mathord{-}\hspace{0.278em} 642 \hspace{0.278em}\mathord{-}\hspace{0.278em} 11409 \hspace{0.278em}\mathord{-}\hspace{0.278em} 0 \hspace{0.222em}\mathord{\_}\hspace{0.222em} 16$](https://doi.org/10.1007/978-3-642-11409-0_16).

<a id="n-60f1c429739a141002db4aada6c12b421055343994ffb3fbe6f9bc774f8b4f7a"></a>

\[Kin97\] Valerie King. “A Simpler Minimum Spanning Tree Verification Algorithm”. In: *Algorithmica* 18 (1997), pp. 263–270. <span style="font-variant:small-caps">doi</span>: [$10 \hspace{0.222em}\mathord{.}\hspace{0.222em} 1007 \hspace{0.222em}\mathord{/}\hspace{0.222em} \mathrm{BF} 02526037$](https://doi.org/10.1007/BF02526037).

<a id="n-e75eb0bf3c6397d022bfc5ade1b54af6ea0d707afd9a99a6b51a61aef1c86fb3"></a>

\[Zwi09\] Uri Zwick. *Verification of Minimum Spanning Trees*. Lecture notes for “Advanced Graph Algorithms”, Tel Aviv University. 2009. <span style="font-variant:small-caps">url</span>: [$\mathrm{https} \hspace{0.278em}\mathord{:}\hspace{0pt} \hspace{0.278em}\mathord{/}\hspace{0pt} \hspace{0.222em}\mathord{/}\hspace{0.222em} \mathrm{www} \hspace{0.222em}\mathord{.}\hspace{0.222em} \mathrm{cs} \hspace{0.222em}\mathord{.}\hspace{0.222em} \mathrm{tau} \hspace{0.222em}\mathord{.}\hspace{0.222em} \mathrm{ac} \hspace{0.222em}\mathord{.}\hspace{0.222em} \mathrm{il} \hspace{0.222em}\mathord{/}\hspace{0.222em} \mathrm{\~{}zwick} \hspace{0.222em}\mathord{/}\hspace{0.222em} \mathrm{grad} \hspace{0.278em}\mathord{-}\hspace{0.278em} \mathrm{algo} \hspace{0.278em}\mathord{-}\hspace{0.278em} 0910 \hspace{0.222em}\mathord{/}\hspace{0.222em} \mathrm{mst} \hspace{0.278em}\mathord{-}\hspace{0.278em} \mathrm{verify} \hspace{0.222em}\mathord{.}\hspace{0.222em} \mathrm{pdf}$](https://www.cs.tau.ac.il/~zwick/grad-algo-0910/mst-verify.pdf).

</section>

</div>

<aside id="n-6dffafb980bbac2eb82c0f3631f95b08bdcac18719a85e684a0a9d189b6632dd">



<a id="n-0ffc2c6f54ca8584bdeb5b46cc9e8a30d15b144976e82e1c7533980578b636ff"></a>
