For the complete documentation index, see llms.txt. This page is also available as Markdown.

23. All-Pairs Shortest Paths

Exercises

23.1-1

Each iteration of Slow-APSP produces the following matrices:

  1. L(1)=(01102208403705100)L^{(1)} = \begin{pmatrix} 0 & \infty & \infty & \infty & -1 & \infty \\ 1 & 0 & \infty & 2 & \infty & \infty \\ \infty & 2 & 0 & \infty & \infty & -8 \\ -4 & \infty & \infty & 0 & 3 & \infty \\ \infty & 7 & \infty & \infty & 0 & \infty \\ \infty & 5 & 10 & \infty & \infty & 0 \end{pmatrix}

  2. L(2)=(061202033048410058790651070)L^{(2)} = \begin{pmatrix} 0 & 6 & \infty & \infty & -1 & \infty \\ -2 & 0 & \infty & 2 & 0 & \infty \\ 3 & -3 & 0 & 4 & \infty & -8 \\ -4 & 10 & \infty & 0 & -5 & \infty \\ 8 & 7 & \infty & 9 & 0 & \infty \\ 6 & 5 & 10 & 7 & \infty & 0 \end{pmatrix}

  3. L(3)=(06812023230128420557903510750)L^{(3)} = \begin{pmatrix} 0 & 6 & \infty & 8 & -1 & \infty \\ -2 & 0 & \infty & 2 & -3 & \infty \\ -2 & -3 & 0 & -1 & 2 & -8 \\ -4 & 2 & \infty & 0 & -5 & \infty \\ 5 & 7 & \infty & 9 & 0 & \infty \\ 3 & 5 & 10 & 7 & 5 & 0 \end{pmatrix}

  4. L(4)=(06812023530138420557903510720)L^{(4)} = \begin{pmatrix} 0 & 6 & \infty & 8 & -1 & \infty \\ -2 & 0 & \infty & 2 & -3 & \infty \\ -5 & -3 & 0 & -1 & -3 & -8 \\ -4 & 2 & \infty & 0 & -5 & \infty \\ 5 & 7 & \infty & 9 & 0 & \infty \\ 3 & 5 & 10 & 7 & 2 & 0 \end{pmatrix}

  5. L(5)=(06812023530168420557903510720)L^{(5)} = \begin{pmatrix} 0 & 6 & \infty & 8 & -1 & \infty \\ -2 & 0 & \infty & 2 & -3 & \infty \\ -5 & -3 & 0 & -1 & -6 & -8 \\ -4 & 2 & \infty & 0 & -5 & \infty \\ 5 & 7 & \infty & 9 & 0 & \infty \\ 3 & 5 & 10 & 7 & 2 & 0 \end{pmatrix}

The Faster-APSP algorithm achieves the same result more efficiently by repeatedly squaring the matrices:

  1. L(2)=L(1)L(1)L^{(2)} = L^{(1)} \cdot L^{(1)}

  2. L(4)=L(2)L(2)L^{(4)} = L^{(2)} \cdot L^{(2)}

  3. L(8)=L(4)L(4)=L(5)L^{(8)} = L^{(4)} \cdot L^{(4)}=L^{(5)} by equation (23.4)

23.1-2

Available in the latest revision of the IM.

23.1-3

Available in the latest revision of the IM.

23.1-4

Available in the latest revision of the IM.

23.1-5

Available in the latest revision of the IM.

23.1-6

Slow-APSP still works correctly, although not producing the same intermediary matrices as the original variant (it "converges" faster). The core insight is that lij(r1)+wjj=lij(r1)l_{ij}^{(r-1)}+w_{jj}=l_{ij}^{(r-1)} represents the "old" value at the start of the procedure. Obviously, lij(r)lij(r1)l_{ij}^{(r)} \le l_{ij}^{(r-1)} (this is how Relax behaves), so initially "setting" lij(r)=lij(r1)l_{ij}^{(r)} = l_{ij}^{(r-1)} is safe. During the updates of some row ii (rows are independent of each other) it could happen that lijl_{ij} uses an already updated value lijl_{ij'} where j<jj'<j. But this doesn't cause any issue at the end, just that some temporary values may be fast forwarded in time.

Faster-APSP doesn't need the matrix MM neither. For the same reason as above, relying on the Relax feature, it can only converge faster.

The Extend-Shortest-Paths procedure operates within a mathematical structure often called a min-plus algebra (or tropical semiring). Because the operations are associative (see Exercise 23.1-4) and bounded by the true shortest-path weights, any sequence of valid edge relaxations that covers the graph will reach the correct answer. The in-place "fast-forwarding" is simply a mathematically valid, albeit less uniform, traversal of these associative path groupings.

See also Exercise 23.2-4.

23.1-7

Available in the latest revision of the IM.

23.1-8

Available in the latest revision of the IM.

23.1-9

Available in the latest revision of the IM.

23.1-10

Available in the latest revision of the IM.

23.2-1

  • D(0)=(01102208403705100)D^{(0)} = \begin{pmatrix} 0 & \infty & \infty & \infty & -1 & \infty \\ 1 & 0 & \infty & 2 & \infty & \infty \\ \infty & 2 & 0 & \infty & \infty & -8 \\ -4 & \infty & \infty & 0 & 3 & \infty \\ \infty & 7 & \infty & \infty & 0 & \infty \\ \infty & 5 & 10 & \infty & \infty & 0 \end{pmatrix}

  • D(1)=(011020208405705100)D^{(1)} = \begin{pmatrix} 0 & \infty & \infty & \infty & -1 & \infty \\ 1 & 0 & \infty & 2 & 0 & \infty \\ \infty & 2 & 0 & \infty & \infty & -8 \\ -4 & \infty & \infty & 0 & -5 & \infty \\ \infty & 7 & \infty & \infty & 0 & \infty \\ \infty & 5 & 10 & \infty & \infty & 0 \end{pmatrix}

  • D(2)=(01102032042840587906510750)D^{(2)} = \begin{pmatrix} 0 & \infty & \infty & \infty & -1 & \infty \\ 1 & 0 & \infty & 2 & 0 & \infty \\ 3 & 2 & 0 & 4 & 2 & -8 \\ -4 & \infty & \infty & 0 & -5 & \infty \\ 8 & 7 & \infty & 9 & 0 & \infty \\ 6 & 5 & 10 & 7 & 5 & 0 \end{pmatrix}

  • D(3)=(01102032042840587906510750)D^{(3)} = \begin{pmatrix} 0 & \infty & \infty & \infty & -1 & \infty \\ 1 & 0 & \infty & 2 & 0 & \infty \\ 3 & 2 & 0 & 4 & 2 & -8 \\ -4 & \infty & \infty & 0 & -5 & \infty \\ 8 & 7 & \infty & 9 & 0 & \infty \\ 6 & 5 & 10 & 7 & 5 & 0 \end{pmatrix}

  • D(4)=(01202302041840557903510720)D^{(4)} = \begin{pmatrix} 0 & \infty & \infty & \infty & -1 & \infty \\ -2 & 0 & \infty & 2 & -3 & \infty \\ 0 & 2 & 0 & 4 & -1 & -8 \\ -4 & \infty & \infty & 0 & -5 & \infty \\ 5 & 7 & \infty & 9 & 0 & \infty \\ 3 & 5 & 10 & 7 & 2 & 0 \end{pmatrix}

  • D(5)=(06812023020418420557903510720)D^{(5)} = \begin{pmatrix} 0 & 6 & \infty & 8 & -1 & \infty \\ -2 & 0 & \infty & 2 & -3 & \infty \\ 0 & 2 & 0 & 4 & -1 & -8 \\ -4 & 2 & \infty & 0 & -5 & \infty \\ 5 & 7 & \infty & 9 & 0 & \infty \\ 3 & 5 & 10 & 7 & 2 & 0 \end{pmatrix}

  • D(6)=(06812023530168420557903510720)D^{(6)} = \begin{pmatrix} 0 & 6 & \infty & 8 & -1 & \infty \\ -2 & 0 & \infty & 2 & -3 & \infty \\ -5 & -3 & 0 & -1 & -6 & -8 \\ -4 & 2 & \infty & 0 & -5 & \infty \\ 5 & 7 & \infty & 9 & 0 & \infty \\ 3 & 5 & 10 & 7 & 2 & 0 \end{pmatrix}

23.2-2

Available in the latest revision of the IM.

23.2-3

We first prove the hint πij(k)=l    dij(k)dil(k)+wlj\pi_{ij}^{(k)} = l \implies d_{ij}^{(k)} \ge d_{il}^{(k)} + w_{lj} by induction on kk.

  • Base Case (k=0k=0): If πij(0)=l\pi_{ij}^{(0)} = l, equation (23.7) implies that l=il = i, iji \neq j, and wij<w_{ij} < \infty. Substituting ll with ii, the inequality becomes dij(0)dii(0)+wijd_{ij}^{(0)} \ge d_{ii}^{(0)} + w_{ij}, which is trivially true.

  • Inductive Step: Assume the claim holds for k1k-1. If πij(k)=l\pi_{ij}^{(k)} = l, equation (23.8) dictates two possible cases:

    1. kk is not an intermediate vertex: Here, πij(k)=πij(k1)=l\pi_{ij}^{(k)} = \pi_{ij}^{(k-1)} = l and dij(k)=dij(k1)d_{ij}^{(k)} = d_{ij}^{(k-1)}. By the inductive hypothesis, dij(k1)dil(k1)+wljd_{ij}^{(k-1)} \ge d_{il}^{(k-1)} + w_{lj}. Because shortest-path distances never increase as kk grows, dil(k1)dil(k)d_{il}^{(k-1)} \ge d_{il}^{(k)}. Therefore, dij(k)=dij(k1)dil(k1)+wljdil(k)+wljd_{ij}^{(k)} = d_{ij}^{(k-1)} \ge d_{il}^{(k-1)} + w_{lj} \ge d_{il}^{(k)} + w_{lj}.

    2. kk is an intermediate vertex: Here, πij(k)=πkj(k1)=l\pi_{ij}^{(k)} = \pi_{kj}^{(k-1)} = l and dij(k)=dik(k1)+dkj(k1)d_{ij}^{(k)} = d_{ik}^{(k-1)} + d_{kj}^{(k-1)}. Applying the inductive hypothesis to the subpath from kk to jj gives dkj(k1)dkl(k1)+wljd_{kj}^{(k-1)} \ge d_{kl}^{(k-1)} + w_{lj}. Substituting this into the dij(k)d_{ij}^{(k)} equation yields dij(k)dik(k1)+dkl(k1)+wljd_{ij}^{(k)} \ge d_{ik}^{(k-1)} + d_{kl}^{(k-1)} + w_{lj}. We know that dil(k)=min(dil(k1),dik(k1)+dkl(k1))d_{il}^{(k)} = \min(d_{il}^{(k-1)}, d_{ik}^{(k-1)} + d_{kl}^{(k-1)}), which means dil(k)dik(k1)+dkl(k1)d_{il}^{(k)} \le d_{ik}^{(k-1)} + d_{kl}^{(k-1)}. Therefore, dij(k)dil(k)+wljd_{ij}^{(k)} \ge d_{il}^{(k)} + w_{lj}.

The inequality holds for both cases, completing the induction.

Assume for contradiction that Gπ,iG_{\pi, i} contains a cycle c=v0,v1,,vpc = \langle v_0, v_1, \dots, v_p \rangle where v0=vpv_0 = v_p. For every edge (vm1,vm)(v_{m-1}, v_m) in this cycle, the predecessor of vmv_m is vm1v_{m-1}, meaning πi,vm(n)=vm1\pi_{i, v_m}^{(n)} = v_{m-1}. Applying our previously proven inequality with j=vmj = v_m and l=vm1l = v_{m-1} yields:

di,vm(n)di,vm1(n)+w(vm1,vm).d_{i, v_m}^{(n)} \ge d_{i, v_{m-1}}^{(n)} + w(v_{m-1}, v_m).

Summing this inequality for all edges around the cycle cc:

m=1pdi,vm(n)m=1pdi,vm1(n)+m=1pw(vm1,vm).\sum_{m=1}^p d_{i, v_m}^{(n)} \ge \sum_{m=1}^p d_{i, v_{m-1}}^{(n)} + \sum_{m=1}^p w(v_{m-1}, v_m).

Because v0=vpv_0 = v_p, the sum of the distances on the left side is identical to the sum of the distances on the right side. Assuming the graph contains no negative-weight cycles, these distances are finite. Subtracting them from both sides gives:

0m=1pw(vm1,vm)=w(c).0 \ge \sum_{m=1}^p w(v_{m-1}, v_m) = w(c).

Thus, w(c)w(c) would have to be exactly 0. However, the strict inequality condition dij(k1)>dik(k1)+dkj(k1)d_{ij}^{(k-1)} > d_{ik}^{(k-1)} + d_{kj}^{(k-1)} guarantees that predecessor pointers are only updated when a strictly shorter path is found. A 0-weight cycle offers no strict improvement, meaning the algorithm will not alter pointers to form one. Therefore, Gπ,iG_{\pi, i} cannot contain any cycles and is acyclic.

Because Gπ,iG_{\pi, i} is a connected, acyclic subgraph where every reachable vertex has exactly one predecessor leading back to ii, it forms a tree rooted at ii. Since the distances correspond to the proven final shortest paths calculated by Floyd-Warshall, it is indeed a shortest-paths tree.

23.2-4

Available in the latest revision of the IM.

23.2-5

Available in the latest revision of the IM.

23.2-6

Available in the latest revision of the IM.

23.2-7

The recurrence formula is

ϕij(k)={NILif k=0kif k1 and dij(k1)>dik(k1)+dkj(k1)ϕij(k1)otherwise\phi_{ij}^{(k)} = \begin{cases} \text{NIL} & \text{if } k = 0 \\ k & \text{if } k \ge 1 \text{ and } d_{ij}^{(k-1)} > d_{ik}^{(k-1)} + d_{kj}^{(k-1)} \\ \phi_{ij}^{(k-1)} & \text{otherwise}\end{cases}

The following procedure assumes we already know a valid path exists.

The Φ\Phi matrix is conceptually identical to the ss table used in the matrix-chain multiplication algorithm:

  • Optimal Splitting: In matrix-chain multiplication, the s[i,j]s[i, j] table stores the optimal index kk used to split the product sequence AiAjA_i \dots A_j into two smaller halves.

  • Divide and Conquer: Similarly, the Φ[i,j]\Phi[i, j] matrix stores the optimal vertex kk, or NIL, that strictly splits the shortest path from ii to jj into two optimal subpaths: iki \leadsto k and kjk \leadsto j. Both tables act as blueprints for reconstructing a solution recursively from the top down.

23.2-8

Available in the latest revision of the IM.

23.2-9

Available in the latest revision of the IM.

23.3-1

(u,v)(u,v)

w(u,v)w(u,v)

w(u,v)+h(u)h(v)w(u,v)+h(u)−h(v)

w^(u,v)\hat w(u,v)

(1,5)(1, 5)

1-1

1+(5)(6)-1 + (-5) - (-6)

00

(2,1)(2, 1)

11

1+(3)(5)1 + (-3) - (-5)

33

(2,4)(2, 4)

22

2+(3)(1)2 + (-3) - (-1)

00

(3,2)(3, 2)

22

2+0(3)2 + 0 - (-3)

55

(3,6)(3, 6)

8-8

8+0(8)-8 + 0 - (-8)

00

(4,1)(4, 1)

4-4

4+(1)(5)-4 + (-1) - (-5)

00

(4,5)(4, 5)

33

3+(1)(6)3 + (-1) - (-6)

88

(5,2)(5, 2)

77

7+(6)(3)7 + (-6) - (-3)

44

(6,2)(6, 2)

55

5+(8)(3)5 + (-8) - (-3)

00

(6,3)(6, 3)

1010

10+(8)010 + (-8) - 0

22

23.3-2

Available in the latest revision of the IM.

23.3-3

Available in the latest revision of the IM.

23.3-4

Available in the latest revision of the IM.

23.3-5

Available in the latest revision of the IM.

23.3-6

Available in the latest revision of the IM.

Problems

23-1 Transitive closure of a dynamic graph

Available in the latest revision of the IM.

23-2 Shortest paths in ϵ-dense graphs

a.

A dd-ary min-heap containing nn elements has a height of Θ(logdn)\Theta(\log_d n):

  • INSERT: Adding an element at the bottom and bubbling it up takes time proportional to the height of the tree. The running time is O(logdn)O(\log_d n).

  • EXTRACT-MIN: Removing the root, replacing it with the last leaf, and trickling it down requires comparing up to dd children at each level to find the minimum. Over the height of the tree, this yields a running time of O(dlogdn)O(d \log_d n).

  • DECREASE-KEY: Decreasing a key's value and bubbling it up towards the root takes time proportional to the height. The running time is O(logdn)O(\log_d n).

The running times when d=Θ(nα)d = \Theta(n^\alpha) for a constant 0<α10 < \alpha \le 1 are based on the next observation:

logdn=lgnlg(nα)=lgnαlgn=1α=O(1).\log_d n = \frac{\lg n}{\lg(n^\alpha)} = \frac{\lg n}{\alpha \lg n} = \frac{1}{\alpha} = O(1).

Applying this constant height to the standard operations:

  • INSERT: O(1)O(1)

  • EXTRACT-MIN: O(nα1)=O(nα)O(n^\alpha \cdot 1) = O(n^\alpha)

  • DECREASE-KEY: O(1)O(1)

A Fibonacci heap has amortized running times of O(1)O(1) for INSERT, O(1)O(1) for DECREASE-KEY, and O(logn)=o(nα)O(\log n)=o(n^\alpha) for EXTRACT-MIN.

b.

Run Dijkstra's algorithm using a dd-ary min-heap where d=Vϵd = \vert{}V\vert{}^\epsilon:

  • Each of the E\vert{}E\vert{} DECREASE-KEY operations takes O(1)O(1) time. The total time for all DECREASE-KEY operations is O(E)O(E).

  • Each of the V\vert{}V\vert{} EXTRACT-MIN operations takes O(dlogdV)=O(Vϵ)O(d \log_d \vert{}V\vert{})=O(\vert{}V\vert{}^\epsilon) time. The total time for all EXTRACT-MIN operations is O(V1+ϵ)=O(E)O(\vert{}V\vert{}^{1+\epsilon})=O(E).

Summing the costs of both primary operations yields a final asymptotic running time of O(E)O(E).

c.

Run the algorithm of part (b) from each vertex resulting in O(VE)O(VE) total time.

d.

Apply the idea from Johnson’s algorithm for sparse graphs by first reweighting the edges and then running part (c).

Last updated