Algorithm Search⌘K

Proofs: Contraction hierarchies

These are the human proofs of Contraction hierarchies, at full length.

Contraction hierarchy queries return shortest paths full

This proof shows: correctness, termination.

Claim. Let all weights be nonnegative and let the hierarchy be built by lines L1 to L5 with any order. For all s,ts, t, the query returns dist⁡G(s,t)\operatorname{dist}_G(s, t), and when it is finite, a walk in GG from ss to tt of that weight.

Setup. Let rank⁡(v)\operatorname{rank}(v) be the position of vv in the order. Let GvG_v be the remaining graph just before vv is contracted: its vertices are those of rank at least rank⁡(v)\operatorname{rank}(v), and its edges are the original edges among them and the shortcuts added so far, each pair keeping its least weight. Let HH be the graph of all edges that are ever stored as upward or downward edges in line L5, with their stored weights. An edge between aa and bb can only be added or lowered while both are uncontracted, and it is stored, with its final weight, when the first of them is contracted; so each edge of HH is stored once, and for vv of lower rank than uu and xx, the edges (u,v)(u, v) and (v,x)(v, x) of GvG_v have the same weights in HH.

Step 1: HH has the distances of GG. By induction on the contractions, every edge of every GvG_v is an edge of GG or a shortcut (u,x)(u, x) of weight w(u,v)+w(v,x)w(u, v) + w(v, x) for edges of an earlier remaining graph, so each edge of HH has the weight of a walk in GG between its ends. Every edge of GG that is not a self-loop is in GvG_v for the lower end vv with at most its weight, so it is in HH with at most its weight. Hence dist⁡H=dist⁡G\operatorname{dist}_H = \operatorname{dist}_G, and expanding an HH-walk edge by edge (each shortcut through its middle, recursively, which ends since middles have lower rank than both ends) gives a GG-walk of the same weight.

Step 2: a shortest up-down walk exists. Call an ss-tt walk in HH up-down if no inner vertex has lower rank than both its neighbors on the walk; then the ranks rise to a top vertex and then fall. Suppose dist⁡(s,t)<∞\operatorname{dist}(s, t) < \infty. For a walk PP let c(P)∈Nnc(P) \in \mathbb{N}^n count, for each rank rr, the inner vertices of PP of rank rr, and order these vectors lexicographically starting from rank 0; this order on Nn\mathbb{N}^n is a well-order. Among shortest ss-tt walks in HH choose PP with the least c(P)c(P). If PP is not up-down, it has an inner vertex vv with neighbors u,xu, x on PP of higher rank, edges (u,v),(v,x)(u, v), (v, x). Then u≠xu \ne x, since otherwise u,v,uu, v, u is a closed walk that can be cut out, giving a shortest walk with smaller cc. When vv was contracted, uu and xx were in GvG_v with these edges. By line L3, either GvG_v without vv had a uu-xx walk WW of weight at most w(u,v)+w(v,x)w(u, v) + w(v, x), all of whose vertices have rank above rank⁡(v)\operatorname{rank}(v), or line L4 put an edge (u,x)(u, x) of weight at most w(u,v)+w(v,x)w(u, v) + w(v, x) into Gv′G_{v'} for the next vertex v′v', which takes the role of WW. Each edge of WW lies in a later remaining graph, so it is in HH with weight at most its weight in WW. Replacing u,v,xu, v, x by WW gives an ss-tt walk of weight at most w(P)w(P), hence shortest, in which one inner occurrence of rank rank⁡(v)\operatorname{rank}(v) is removed and only inner vertices of higher rank are added. Its count vector is lexicographically smaller, a contradiction. So PP is up-down.

Step 3: the two searches compute upward distances. The forward search is Dijkstra's algorithm from ss on the upward edges, and the backward search is Dijkstra's algorithm from tt on the reversed downward edges, both with nonnegative weights. Let d↑(v)d^\uparrow(v) be the least weight of an ss-vv walk in HH whose ranks increase, and d↓(v)d^\downarrow(v) the least weight of a vv-tt walk whose ranks decrease. Every edge of HH joins vertices of different rank and is stored as an upward edge out of its lower end or as a downward edge into its lower end, so these are exactly the graphs the two searches use. When a side scans vv, its label is d↑(v)d^\uparrow(v) (or d↓(v)d^\downarrow(v)), by the correctness of Dijkstra; and every tentative label is the weight of a real walk.

Step 4: the query is correct. Every value given to μ\mu in line L8 is a scanned label plus a tentative or final label of the other side, the weight of an ss-tt walk in HH, so μ≥dist⁡(s,t)\mu \ge \operatorname{dist}(s, t) always. If dist⁡(s,t)=∞\operatorname{dist}(s, t) = \infty, no such walk exists, line L8 never remembers a vertex, and line L9 returns ∞\infty. Otherwise let PP be a shortest up-down walk (Step 2) with top vertex zz; its two halves give d↑(z)+d↓(z)≤w(P)=dist⁡(s,t)d^\uparrow(z) + d^\downarrow(z) \le w(P) = \operatorname{dist}(s, t). Suppose the query stops with μ>dist⁡(s,t)\mu > \operatorname{dist}(s, t). Then both least keys were at least μ>d↑(z)\mu > d^\uparrow(z) and >d↓(z)> d^\downarrow(z), and Dijkstra scans in nondecreasing key order, so both sides had already scanned zz with its final labels. At the later of the two scans, line L8 set μ≤d↑(z)+d↓(z)≤dist⁡(s,t)\mu \le d^\uparrow(z) + d^\downarrow(z) \le \operatorname{dist}(s, t), and μ\mu never increases, a contradiction. So μ=dist⁡(s,t)\mu = \operatorname{dist}(s, t). The remembered vertex yy has labels whose walks, read through the predecessors, form an ss-tt walk in HH of weight μ\mu (labels only fall, and the predecessor chain of the last setting has exactly that weight), and by Step 1 its expansion is a walk in GG of the same weight.

Termination. The contraction loop handles each vertex once and each witness search is a Dijkstra search on a finite graph. Each query side scans each vertex at most once, the loop stops when both heaps are empty or both least keys reach μ\mu, and the expansion ends by Step 1. ■\blacksquare

Back to Contraction hierarchies