Algorithm Search⌘K

Proofs: Shortest paths in a DAG

These are the human proofs of Shortest paths in a DAG, at full length.

Relaxing in topological order gives shortest paths in a DAG full

This proof shows: correctness, termination.

Claim. Let G=(V,E)G = (V, E) be a directed acyclic graph with real weights ww and a source ss. DAG-SHORTEST-PATHS(G,w,s)(G, w, s) ends, and at the end d[v]=δ(s,v)d[v] = \delta(s, v) for each v∈Vv \in V. For each v≠sv \ne s with d[v]<∞d[v] < \infty, π[v]≠\pi[v] \ne nil and d[v]=d[π[v]]+w(π[v],v)d[v] = d[\pi[v]] + w(\pi[v], v).

Termination. Line L1 ends (Kahn's algorithm makes at most nn passes of its loop). The loop of line L4 visits each of the nn vertices once, and the inner loop visits each edge out of the current vertex once. So the algorithm ends.

Setup. Let v1,v2,…,vnv_1, v_2, \ldots, v_n be the order from line L1: for each edge (vi,vj)(v_i, v_j), i<ji < j. Since GG has no cycle, every walk is a path, so δ(s,v)\delta(s, v) is the least weight of a path from ss to vv (there are finitely many), or ∞\infty if there is none. A path visits vertices in increasing position, because each edge goes forward. We use the upper-bound property: d[v]≥δ(s,v)d[v] \ge \delta(s, v) at all times, and d[v]d[v] never increases.

Invariant. For 1≤j≤n+11 \le j \le n + 1: when the loop of line L4 is about to visit vjv_j (or has ended, for j=n+1j = n + 1), d[vi]=δ(s,vi)d[v_i] = \delta(s, v_i) for each i≤ji \le j (for i≤ni \le n).

We prove the stronger statement P(j)P(j): at the moment the loop starts the visit of vjv_j, d[vj]=δ(s,vj)d[v_j] = \delta(s, v_j). Values do not change after they equal δ\delta (they cannot go lower), and a vertex is visited before all later ones, so P(1),…,P(n)P(1), \ldots, P(n) give the invariant and the claim.

Proof of P(j)P(j), by strong induction on jj. Assume P(i)P(i) for all i<ji < j.

Case δ(s,vj)=∞\delta(s, v_j) = \infty. By the upper-bound property d[vj]=∞d[v_j] = \infty.

Case vj=sv_j = s. No path from ss to ss has an edge, because a nonempty one would be a cycle; so δ(s,s)=0\delta(s, s) = 0. d[s]=0d[s] = 0 by line L3, and it never drops below δ(s,s)=0\delta(s, s) = 0.

Case vj≠sv_j \ne s and δ(s,vj)<∞\delta(s, v_j) < \infty. Take a shortest path s⇝vi→vjs \leadsto v_i \to v_j. Its last edge goes forward, so i<ji < j, and its prefix s⇝vis \leadsto v_i is a shortest path to viv_i: a shorter path to viv_i plus the edge would give a shorter path to vjv_j, and it would still be a path, since GG has no cycle. So δ(s,vj)=δ(s,vi)+w(vi,vj)\delta(s, v_j) = \delta(s, v_i) + w(v_i, v_j) and δ(s,vi)<∞\delta(s, v_i) < \infty. By P(i)P(i), d[vi]=δ(s,vi)<∞d[v_i] = \delta(s, v_i) < \infty when viv_i is visited, so line L5 lets the inner loop run, and line L7 relaxes (vi,vj)(v_i, v_j). After it, d[vj]≤d[vi]+w(vi,vj)=δ(s,vj)d[v_j] \le d[v_i] + w(v_i, v_j) = \delta(s, v_j). Later steps before the visit of vjv_j only lower d[vj]d[v_j], and the upper-bound property gives d[vj]≥δ(s,vj)d[v_j] \ge \delta(s, v_j). So d[vj]=δ(s,vj)d[v_j] = \delta(s, v_j) when the visit of vjv_j starts. This proves P(j)P(j).

Predecessors. Let v≠sv \ne s with d[v]<∞d[v] < \infty. Then d[v]d[v] was set by line L8, which also set π[v]=u\pi[v] = u with d[v]=d[u]+w(u,v)d[v] = d[u] + w(u, v) at that time, and uu was being visited, so d[u]=δ(s,u)d[u] = \delta(s, u) was already final. Later, d[v]d[v] changes only together with π[v]\pi[v]. So at the end d[v]=d[π[v]]+w(π[v],v)d[v] = d[\pi[v]] + w(\pi[v], v). Each predecessor comes earlier in the order, so following π\pi from vv ends, and it ends at ss, the only reachable vertex without a predecessor. Thus the predecessor edges form a shortest-path tree. ■\blacksquare

Where acyclicity is used. Twice: a shortest path to vjv_j enters it from an earlier vertex, and the prefix of a shortest path, extended by an edge, is still a path. With a cycle, both steps fail; this is why line L1 must check for one.

Back to Shortest paths in a DAG