# Ch24: Single-Source Shortest Paths ###### tags: `algorithm` :::success - contributed by < `TYChan6028` > - textbook: [Introduction to Algorithms, Third Edition](https://mitpress.mit.edu/books/introduction-algorithms-third-edition) ::: ## Exercises 24.1 ### *24.1-1* Run the Bellman-Ford algorithm on the directed graph of Figure 24.4, using vertex $z$ as the source. In each pass, relax edges in the same order as in the figure, and show the $d$ and $\pi$ values after each pass. Now, change the weight of edge $(z,x)$ to 4 and run the algorithm again, using $s$ as the source. Order of traverse: $z \rightarrow y \rightarrow s \rightarrow t \rightarrow x$ ```graphviz digraph row_1 { forcelabels=true node [shape="circle", style=filled, fillcolor=transparent] edge [color="#78a0bf", fontcolor=navy, len=2] nodesep=1.5 subgraph cluster_1 { label="Original" labelloc="b" color="transparent" s [label="&#8734;", xlabel="s"] t [label="&#8734;", xlabel="t"] x [label="&#8734;", xlabel="x"] y [label="&#8734;", xlabel="y"] z [label=0, xlabel="z", fillcolor="#fbf8e5"] s -> t [headlabel="6"] s -> y [headlabel="7"] t -> x [headlabel="5"] t -> z [headlabel="-4"] t -> y [headlabel="8"] x -> t [headlabel="-2"] y -> z [headlabel="9"] y -> x [xlabel="-3"] z -> s [xlabel="2"] z -> x [headlabel="7"] {rank=same;s t x} {rank=same;y z} } subgraph cluster_2 { label="Pass 1" labelloc="b" color="transparent" s2 [label=2, xlabel="s"] t2 [label=5, xlabel="t"] x2 [label=7, xlabel="x"] y2 [label=9, xlabel="y"] z2 [label=0, xlabel="z", fillcolor="#fbf8e5"] s2 -> t2 [headlabel="6"] s2 -> y2 [headlabel="7", color=red] t2 -> x2 [headlabel="5"] t2 -> z2 [headlabel="-4"] t2 -> y2 [headlabel="8"] x2 -> t2 [headlabel="-2", color=red] y2 -> z2 [headlabel="9"] y2 -> x2 [xlabel="-3"] z2 -> s2 [xlabel="2", color=red] z2 -> x2 [headlabel="7", color=red] {rank=same;s2 t2 x2} {rank=same;y2 z2} } } ``` ```graphviz digraph row_2 { forcelabels=true node [shape="circle", style=filled, fillcolor=transparent] edge [color="#78a0bf", fontcolor=navy, len=2] nodesep=1.5 subgraph cluster_3 { label="Pass 2" labelloc="b" color="transparent" s3 [label=2, xlabel="s"] t3 [label=4, xlabel="t"] x3 [label=6, xlabel="x"] y3 [label=9, xlabel="y"] z3 [label=0, xlabel="z", fillcolor="#fbf8e5"] s3 -> t3 [headlabel="6"] s3 -> y3 [headlabel="7", color=red] t3 -> x3 [headlabel="5"] t3 -> z3 [headlabel="-4"] t3 -> y3 [headlabel="8"] x3 -> t3 [headlabel="-2", color=red] y3 -> z3 [headlabel="9"] y3 -> x3 [xlabel="-3", color=red] z3 -> s3 [xlabel="2", color=red] z3 -> x3 [headlabel="7"] {rank=same;s3 t3 x3} {rank=same;y3 z3} } subgraph cluster_4 { label="Pass 3" labelloc="b" color="transparent" s4 [label=2, xlabel="s"] t4 [label=4, xlabel="t"] x4 [label=6, xlabel="x"] y4 [label=9, xlabel="y"] z4 [label=0, xlabel="z", fillcolor="#fbf8e5"] s4 -> t4 [headlabel="6"] s4 -> y4 [headlabel="7", color=red] t4 -> x4 [headlabel="5"] t4 -> z4 [headlabel="-4"] t4 -> y4 [headlabel="8"] x4 -> t4 [headlabel="-2", color=red] y4 -> z4 [headlabel="9"] y4 -> x4 [xlabel="-3", color=red] z4 -> s4 [xlabel="2", color=red] z4 -> x4 [headlabel="7"] {rank=same;s4 t4 x4} {rank=same;y4 z4} } } ``` ```graphviz digraph row_3 { label="Pass 4 (final)" labelloc="b" color="transparent" forcelabels=true node [shape="circle", style=filled, fillcolor=transparent] edge [color="#78a0bf", fontcolor=navy, len=2] nodesep=1.5 s5 [label=2, xlabel="s"] t5 [label=4, xlabel="t"] x5 [label=6, xlabel="x"] y5 [label=9, xlabel="y"] z5 [label=0, xlabel="z", fillcolor="#fbf8e5"] s5 -> t5 [headlabel="6"] s5 -> y5 [headlabel="7", color=red] t5 -> x5 [headlabel="5"] t5 -> z5 [headlabel="-4"] t5 -> y5 [headlabel="8"] x5 -> t5 [headlabel="-2", color=red] y5 -> z5 [headlabel="9"] y5 -> x5 [xlabel="-3", color=red] z5 -> s5 [xlabel="2", color=red] z5 -> x5 [headlabel="7"] {rank=same;s5 t5 x5} {rank=same;y5 z5} } ``` The graph with $w(z,x)=4$ and $s$ as the source can be obtained by using the same process. ### *24.1-2* Prove Corollary 24.3. > ***Corollary 24.3*** > Let $G=(V,E)$ be a weighted, directed graph with source vertex $s$ and weight function $w:E \rightarrow \mathbb{R}$, and assume that $G$ contains no negative-weight cycles that are reachable from s. Then, for each vertex $v \in V$, there is a path from $s$ to $v$ if and only if `BELLMAN-FORD` terminates with $v.d<\infty$ when it is run on $G$. -- <cite>textbook, p.653</cite> #### *Proof* We will prove this by contradiction. Let graph $G$ be initialized with a call to `INITIALIZE- SINGLE-SOURCE`, which sets $s.d=0$ and $v.d=\infty$ for $v \in V-\{s\}$. At `BELLMAN-FORD`'s termination, assume there exists a $v.d=\infty$ on the path $p=<v_0, v_1,..., v_k>$ from $s \rightsquigarrow v$, where $s=v_0$ and $v=v_k$. Since $v.d=\delta(s,v)$ for all $v \in V$ at termination, $\begin{eqnarray} v.d &=& \delta(s,v_k)\\ &=& \infty\\ &\leq& \delta(s,v_{k-1})+w(v_{k-1},v_k)\\ \end{eqnarray}$ We know $w(v_{k-1},v_k) \neq \infty$, so $\delta(s,v_{k-1})=\infty$. The same can be said for $\delta(s,v_{k-1})$ to $\delta(s,v_1)$, until $\begin{eqnarray} \delta(s,v_1) &=& \infty\\ &\leq& \delta(s,v_0)+w(s,v_1)\\ &=& \delta(s,s)+w(s,1)\\ \Longrightarrow \delta(s,s) &=& \infty \end{eqnarray}$ This contradicts with $s.d=0$, which proves there is no path from $s$ to $v$ if `BELLMAN-FORD` terminates with $v.d=\infty$. ## Exercises 24.2 ### *24.2-1* Run `DAG-SHORTEST-PATHS` on the directed graph of Figure 24.5, using vertex $r$ as the source. ```graphviz digraph dag { label="Original" labelloc="b" color="transparent" forcelabels=true node [shape="circle", style=filled, fillcolor=transparent] edge [color="#78a0bf", fontcolor=navy, len=2] nodesep=1.5 r [label=0, xlabel="r", fillcolor="#fbf8e5"] s [label="&#8734;", xlabel="s"] t [label="&#8734;", xlabel="t"] x [label="&#8734;", xlabel="x"] y [label="&#8734;", xlabel="y"] z [label="&#8734;", xlabel="z"] r -> s [xlabel="5"] s -> t [xlabel="2"] t -> x [xlabel="7"] x -> y [xlabel="-1"] y -> z [xlabel="-2"] r:s -> t [xlabel="3"] s -> x [xlabel="6"] x -> z [xlabel="1"] t:s -> y [xlabel="4"] t:s -> z [xlabel="2"] {rank=same;r s t x y z} } ``` ```graphviz digraph dag { label="Explore r" labelloc="b" color="transparent" forcelabels=true node [shape="circle", style=filled, fillcolor=transparent] edge [color="#78a0bf", fontcolor=navy, len=2] nodesep=1.5 r [label=0, xlabel="r", fillcolor="#fbf8e5"] s [label=5, xlabel="s"] t [label=3, xlabel="t"] x [label="&#8734;", xlabel="x"] y [label="&#8734;", xlabel="y"] z [label="&#8734;", xlabel="z"] r -> s [xlabel="5", color=red] s -> t [xlabel="2"] t -> x [xlabel="7"] x -> y [xlabel="-1"] y -> z [xlabel="-2"] r:s -> t [xlabel="3", color=red] s -> x [xlabel="6"] x -> z [xlabel="1"] t:s -> y [xlabel="4"] t:s -> z [xlabel="2"] {rank=same;r s t x y z} } ``` ```graphviz digraph dag { label="Explore s" labelloc="b" color="transparent" forcelabels=true node [shape="circle", style=filled, fillcolor=transparent] edge [color="#78a0bf", fontcolor=navy, len=2] nodesep=1.5 r [label=0, xlabel="r", fillcolor="#fbf8e5"] s [label=5, xlabel="s"] t [label=3, xlabel="t"] x [label=11, xlabel="x"] y [label="&#8734;", xlabel="y"] z [label="&#8734;", xlabel="z"] r -> s [xlabel="5", color=red] s -> t [xlabel="2"] t -> x [xlabel="7"] x -> y [xlabel="-1"] y -> z [xlabel="-2"] r:s -> t [xlabel="3", color=red] s -> x [xlabel="6", color=red] x -> z [xlabel="1"] t:s -> y [xlabel="4"] t:s -> z [xlabel="2"] {rank=same;r s t x y z} } ``` ```graphviz digraph dag { label="Explore t" labelloc="b" color="transparent" forcelabels=true node [shape="circle", style=filled, fillcolor=transparent] edge [color="#78a0bf", fontcolor=navy, len=2] nodesep=1.5 r [label=0, xlabel="r", fillcolor="#fbf8e5"] s [label=5, xlabel="s"] t [label=3, xlabel="t"] x [label=10, xlabel="x"] y [label=7, xlabel="y"] z [label=5, xlabel="z"] r -> s [xlabel="5", color=red] s -> t [xlabel="2"] t -> x [xlabel="7", color=red] x -> y [xlabel="-1"] y -> z [xlabel="-2"] r:s -> t [xlabel="3", color=red] s -> x [xlabel="6"] x -> z [xlabel="1"] t:s -> y [xlabel="4", color=red] t:s -> z [xlabel="2", color=red] {rank=same;r s t x y z} } ``` ```graphviz digraph dag { label="Explore x" labelloc="b" color="transparent" forcelabels=true node [shape="circle", style=filled, fillcolor=transparent] edge [color="#78a0bf", fontcolor=navy, len=2] nodesep=1.5 r [label=0, xlabel="r", fillcolor="#fbf8e5"] s [label=5, xlabel="s"] t [label=3, xlabel="t"] x [label=10, xlabel="x"] y [label=7, xlabel="y"] z [label=5, xlabel="z"] r -> s [xlabel="5", color=red] s -> t [xlabel="2"] t -> x [xlabel="7", color=red] x -> y [xlabel="-1"] y -> z [xlabel="-2"] r:s -> t [xlabel="3", color=red] s -> x [xlabel="6"] x -> z [xlabel="1"] t:s -> y [xlabel="4", color=red] t:s -> z [xlabel="2", color=red] {rank=same;r s t x y z} } ``` ```graphviz digraph dag { label="Explore y" labelloc="b" color="transparent" forcelabels=true node [shape="circle", style=filled, fillcolor=transparent] edge [color="#78a0bf", fontcolor=navy, len=2] nodesep=1.5 r [label=0, xlabel="r", fillcolor="#fbf8e5"] s [label=5, xlabel="s"] t [label=3, xlabel="t"] x [label=10, xlabel="x"] y [label=7, xlabel="y"] z [label=5, xlabel="z"] r -> s [xlabel="5", color=red] s -> t [xlabel="2"] t -> x [xlabel="7", color=red] x -> y [xlabel="-1"] y -> z [xlabel="-2"] r:s -> t [xlabel="3", color=red] s -> x [xlabel="6"] x -> z [xlabel="1"] t:s -> y [xlabel="4", color=red] t:s -> z [xlabel="2", color=red] {rank=same;r s t x y z} } ``` ```graphviz digraph dag { label="Explore z (final)" labelloc="b" color="transparent" forcelabels=true node [shape="circle", style=filled, fillcolor=transparent] edge [color="#78a0bf", fontcolor=navy, len=2] nodesep=1.5 r [label=0, xlabel="r", fillcolor="#fbf8e5"] s [label=5, xlabel="s"] t [label=3, xlabel="t"] x [label=10, xlabel="x"] y [label=7, xlabel="y"] z [label=5, xlabel="z"] r -> s [xlabel="5", color=red] s -> t [xlabel="2"] t -> x [xlabel="7", color=red] x -> y [xlabel="-1"] y -> z [xlabel="-2"] r:s -> t [xlabel="3", color=red] s -> x [xlabel="6"] x -> z [xlabel="1"] t:s -> y [xlabel="4", color=red] t:s -> z [xlabel="2", color=red] {rank=same;r s t x y z} } ``` ### *24.2-2* Suppose we change line 3 of `DAG-SHORTEST-PATHS` to read `for the first |V| - 1 vertices, taken in topologically sorted order`. Show that the procedure would remain correct. ```javascript DAG-SHORTEST-PATHS(G,w,s) ``` ```javascript= topologically sort the vertices of G INITIALIZE-SINGLE-SOURCE(G,s) for each vertex u, taken in topologically sorted order for each vertex v in G.Adj[u] RELAX(u,v,w) ``` #### *Proof* Let topologically-sorted $V=<v_1,v_2,...,v_k>$, then $v_k$ has no child nodes. This shows that there does not exist a $v_{k+1}$ for which $\delta(s,v_{k+1}) \leq \delta(s,v_k)+w(v_k,v_{k+1})$ could relax. Since `G.Adj[u]`$=\emptyset$, the `for` loop on line `4` would go through 0 iterations. Therefore, it is safe to only consider the first $|V|-1$ vertices. ## Exercises 24.3 ### *24.3-1* Run Dijkstra’s algorithm on the directed graph of Figure 24.2, first using vertex $s$ as the source and then using vertex $z$ as the source. In the style of Figure 24.6, show the $d$ and $\pi$ values and the vertices in set $S$ after each iteration of the `while` loop. ```graphviz digraph row_1 { forcelabels=true node [shape="circle", style=filled, fillcolor=transparent] edge [color="#78a0bf", fontcolor=navy, len=2] nodesep=1.5 subgraph cluster_1 { label="Original" labelloc="b" color="transparent" s [label=0, xlabel="s", fillcolor="#fbf8e5"] t [label="&#8734;", xlabel="t"] x [label="&#8734;", xlabel="x"] y [label="&#8734;", xlabel="y"] z [label="&#8734;", xlabel="z"] s -> t [xlabel="3"] s -> y [xlabel="5"] t -> x [xlabel="6"] t -> y [xlabel="2"] x -> z [xlabel="2"] y -> t [xlabel="1"] y -> x [xlabel="4"] y -> z [xlabel="6"] z -> s [xlabel="3"] z -> x [xlabel="7"] {rank=same;t y} {rank=same;x z} } subgraph cluster_2 { label="S = {s}" labelloc="b" color="transparent" s2 [label=0, xlabel="s", fillcolor="#fbf8e5"] t2 [label=3, xlabel="t"] x2 [label="&#8734;", xlabel="x"] y2 [label=5, xlabel="y"] z2 [label="&#8734;", xlabel="z"] s2 -> t2 [xlabel="3", color=red] s2 -> y2 [xlabel="5", color=red] t2 -> x2 [xlabel="6"] t2 -> y2 [xlabel="2"] x2 -> z2 [xlabel="2"] y2 -> t2 [xlabel="1"] y2 -> x2 [xlabel="4"] y2 -> z2 [xlabel="6"] z2 -> s2 [xlabel="3"] z2 -> x2 [xlabel="7"] {rank=same;t2 y2} {rank=same;x2 z2} } } ``` ```graphviz digraph row_2 { forcelabels=true node [shape="circle", style=filled, fillcolor=transparent] edge [color="#78a0bf", fontcolor=navy, len=2] nodesep=1.5 subgraph cluster_3 { label="S = {s, t}" labelloc="b" color="transparent" s3 [label=0, xlabel="s", fillcolor="#fbf8e5"] t3 [label=3, xlabel="t"] x3 [label=9, xlabel="x"] y3 [label=5, xlabel="y"] z3 [label="&#8734;", xlabel="z"] s3 -> t3 [xlabel="3", color=red] s3 -> y3 [xlabel="5", color=red] t3 -> x3 [xlabel="6", color=red] t3 -> y3 [xlabel="2"] x3 -> z3 [xlabel="2"] y3 -> t3 [xlabel="1"] y3 -> x3 [xlabel="4"] y3 -> z3 [xlabel="6"] z3 -> s3 [xlabel="3"] z3 -> x3 [xlabel="7"] {rank=same;t3 y3} {rank=same;x3 z3} } subgraph cluster_4 { label="S = {s, t, y}" labelloc="b" color="transparent" s4 [label=0, xlabel="s", fillcolor="#fbf8e5"] t4 [label=3, xlabel="t"] x4 [label=9, xlabel="x"] y4 [label=5, xlabel="y"] z4 [label=11, xlabel="z"] s4 -> t4 [xlabel="3", color=red] s4 -> y4 [xlabel="5", color=red] t4 -> x4 [xlabel="6", color=red] t4 -> y4 [xlabel="2"] x4 -> z4 [xlabel="2"] y4 -> t4 [xlabel="1"] y4 -> x4 [xlabel="4"] y4 -> z4 [xlabel="6", color=red] z4 -> s4 [xlabel="3"] z4 -> x4 [xlabel="7"] {rank=same;t4 y4} {rank=same;x4 z4} } } ``` ```graphviz digraph row_3 { forcelabels=true node [shape="circle", style=filled, fillcolor=transparent] edge [color="#78a0bf", fontcolor=navy, len=2] nodesep=1.5 subgraph cluster_5 { label="S = {s, t, y, x}" labelloc="b" color="transparent" s5 [label=0, xlabel="s", fillcolor="#fbf8e5"] t5 [label=3, xlabel="t"] x5 [label=9, xlabel="x"] y5 [label=5, xlabel="y"] z5 [label=11, xlabel="z"] s5 -> t5 [xlabel="3", color=red] s5 -> y5 [xlabel="5", color=red] t5 -> x5 [xlabel="6", color=red] t5 -> y5 [xlabel="2"] x5 -> z5 [xlabel="2"] y5 -> t5 [xlabel="1"] y5 -> x5 [xlabel="4"] y5 -> z5 [xlabel="6", color=red] z5 -> s5 [xlabel="3"] z5 -> x5 [xlabel="7"] {rank=same;t5 y5} {rank=same;x5 z5} } subgraph cluster_6 { label="S = {s, t, y, x, z} (final)" labelloc="b" color="transparent" s6 [label=0, xlabel="s", fillcolor="#fbf8e5"] t6 [label=3, xlabel="t"] x6 [label=9, xlabel="x"] y6 [label=5, xlabel="y"] z6 [label=11, xlabel="z"] s6 -> t6 [xlabel="3", color=red] s6 -> y6 [xlabel="5", color=red] t6 -> x6 [xlabel="6", color=red] t6 -> y6 [xlabel="2"] x6 -> z6 [xlabel="2"] y6 -> t6 [xlabel="1"] y6 -> x6 [xlabel="4"] y6 -> z6 [xlabel="6", color=red] z6 -> s6 [xlabel="3"] z6 -> x6 [xlabel="7"] {rank=same;t6 y6} {rank=same;x6 z6} } } ``` The graph with vertex $z$ as the source can be obtained by using the same process. ### *24.3-2* Give a simple example of a directed graph with negative-weight edges for which Dijkstra’s algorithm produces incorrect answers. Why doesn’t the proof of Theorem 24.6 go through when negative-weight edges are allowed? ```javascript DIJKSTRA(G,w,s) ``` ```javascript= INITIALIZE-SINGLE-SOURCE(G,s) S = empty set Q = G.V while Q != empty set u = EXTRACT-MIN(Q) S = UNION(S,{u}) for each vertex v in G.Adj[u] RELAX(u,v,w) ``` Below is an example for which Dijkstra's algorithm produces an incorrect answer. The negative-weight edge $u \rightarrow z$ creates a negative cycle $y \rightarrow u \rightarrow z \rightarrow y$ for which an even smaller weight can always be achieved by traversing the cycle indefinitely. ```graphviz digraph row_3 { forcelabels=true node [shape="circle", style=filled, fillcolor=transparent] edge [color="#78a0bf", fontcolor=navy, len=2] nodesep=1.5 label="S = {s, x, t, (y, u, z = negative cycle)}" labelloc="b" color="transparent" s6 [label=0, xlabel="s", fillcolor="#fbf8e5"] x6 [label=3, xlabel="x"] y6 [label=8, xlabel="y", fillcolor="#efdfde"] t6 [label=5, xlabel="t"] z6 [label=1, xlabel="z", fillcolor="#efdfde"] u6 [label=10, xlabel="u", fillcolor="#efdfde"] s6 -> x6 [xlabel="3", color=red] s6 -> t6 [xlabel="5", color=red] x6 -> y6 [xlabel="6", color=red] x6 -> t6 [xlabel="2"] y6 -> z6 [xlabel="2"] y6 -> u6 [xlabel="1", color=red] t6 -> x6 [xlabel="1"] t6 -> y6 [xlabel="4"] t6 -> z6 [xlabel="6"] z6 -> s6 [xlabel="3"] z6 -> y6 [xlabel="7", color=red] u6 -> z6 [xlabel="-9", color=red] {rank=same;s6 t6 z6} {rank=same;x6 y6 u6} } ``` > ***Theorem 24.6 (Correctness of Dijkstra’s algorithm)*** > Dijkstra’s algorithm, run on a weighted, directed graph $G=(V,E)$ with non-negative weight function $w$ and source $s$, terminates with $u.d=\delta(s,u)$ for all vertices $u \in V$. Theorem 24.6 proves correctness by showing, for each vertex $u \in V$, $u.d=\delta(s,u)$ at the time when $u$ is added to set $S$. Once the equality is shown, it relies on the upper-bound property to uphold the equality at all times thereafter. Therefore, the algorithm would terminate with $u.d=\delta(s,u)$ for all vertices $u \in S=V$. The proof of Theorem 24.6 illustrates a shortest path from $s \overset{p_1}{\rightsquigarrow} x \rightarrow y \overset{p_2}{\rightsquigarrow} u$, on which $s,x \in S$ and $y,u \in V-S$. It makes a claim that $u$ is the first vertex for which $u.d \neq \delta(s,u)$ when it is added to $S$, then attempts to disprove this by contradiction. By proving $y.d=\delta(s,y)$ and because all edge weights are non-negative, it arrives at the relations \begin{eqnarray} y.d &=& \delta(s,y)\\ &\leq& \delta(s,u)\\ &\leq& u.d \end{eqnarray} Since $y,u \in V-S$ and $u$ is chosen over $y$ to be next included in set $S$, $u.d \leq y.d$. Combined with the relation shown above, $y.d=\delta(s,y)=\delta(s,u)=u.d$, which contradicts its claim and completes the proof. The reason why the proof of Theorem 24.6 does not go through when negative-weight edges are allowed is because we can no longer make the assumption that $\delta(s,y) \leq \delta(s,u)$. We know $y.d=\delta(s,y) \geq u.d$, but if $\delta(s,y)>\delta(s,u)$ due to a negative-weight edge, it is possible that 1. $y.d=\delta(s,y)=u.d>\delta(s,u)$ 2. $\delta(s,y)>u.d=a$ and $\delta(s,y)>\delta(s,u)=b$ for which $a \neq b$