Single-Source Shortest Path
Dijkstra’s Algorithm
(GreedyAlgorithm)
Bellman-Ford (Dynamic Algorithm)
Shortest Paths Problems
1
v t
5 4 9
8 13
u 3 x 4 y
2 10
1 1 2
w z
6
● Given a weighted directed graph,
<u,v,t,x,z> is a path of weight 29 from u to z.
<u,v,w,x,y,z> is another path from u to z; it has
weight 16 and is the shortest path from u to z.
Variants of Shortest Paths
Problems
A. Single pair shortest path problem
○ Given s and d, find shortest path from s to d.
B. Single source shortest paths problem
○ Given s, for each d find shortest path from s to d.
C. All-pairs shortest paths problem
○ For each ordered pair s,d, find shortest path.
● (A) and (B) seem to have same asymptotic complexity.
● (C) takes longer, but not as long as repeating (B) for
each s.
More Shortest Paths Variants
1. All weights are non-negative.
2. Weights may be negative, but no negative cycles
(A cycle is a path from a vertex to itself.)
3. Negative cycles allowed.
Algorithm reports “∞” if there is a negative cycle on path from
source to destination
● (2) and (3) seem to be harder than (1).
v
v 5 u v w
5 u v w
u 2 u 0 5 8 u -3 2 u 0 ∞ ∞
3
v -3 0 3
6
v ∞ ∞ ∞
-6 w -6 -1 0 w
w w ∞ ∞ ∞
Single-Source Shortest Path
● Problem: given a weighted directed graph G,
find the minimum-weight path from a given
source vertex s to another vertex v
■ “Shortest-path” = minimum weight
■ Weight of path is sum of edges
■ E.g., a road map: what is the shortest path from
Chapel Hill to Charlottesville?
Shortest Path Properties
● Again, we have optimal substructure: the
shortest path consists of shortest subpaths:
■ Proof: suppose some subpath is not a shortest path
○ There must then exist a shorter subpath
○ Could substitute the shorter subpath for a shorter path
○ But then overall path is not shortest path. Contradiction
Shortest Path Properties
● Define (u,v) to be the weight of the shortest
path from u to v
● Shortest paths satisfy the triangle inequality:
(u,v) (u,x) + w(x,v)
x
u v
This path is no longer than any other path
Shortest Path Properties
● In graphs with negative weight cycles, some
shortest paths will not exist (Why?):
<0
Relaxation
● A key technique in shortest path algorithms is
relaxation
■ Idea: for all v, maintain upper bound d[v] on (s,v)
Relax(u,v,w) {
if (d[v] > d[u]+w) then d[v]=d[u]+w;
}
2 2
5 9 5 6
Relax Relax
2 2
5 7 5 6
Dijkstra’s Algorithm
Dijkstra(G)
for each v V
d[v] = ;
d[s] = 0; S = ; Q = V;
while (Q )
u = ExtractMin(Q);
S = S U {u};
for each v u->Adj[]
if (d[v] > d[u]+w(u,v)) Relaxation
d[v] = d[u]+w(u,v); Step
Example
u v
1
10
9
2 3
s 0 4 6
5 7
2
x y
Example
u v
1
10
10
9
2 3
s 0 4 6
5 7
5
2
x y
Example
u v
1
8 14
10
9
2 3
s 0 4 6
5 7
5 7
2
x y
Example
u v
1
8 13
10
9
2 3
s 0 4 6
5 7
5 7
2
x y
Example
u v
1
8 9
10
9
2 3
s 0 4 6
5 7
5 7
2
x y
Example
u v
1
8 9
10
9
2 3
s 0 4 6
5 7
5 7
2
x y
Example
B
10 2
source A 4 3 D
5 1
C
Ex: run the algorithm
Dijkstra’s Algorithm
Dijkstra(G)
for each v V How many times is
ExtractMin() called?
d[v] = ;
d[s] = 0; S = ; Q = V;
while (Q ) How many times is
u = ExtractMin(Q); DecraseKey() called?
S = S U {u};
for each v u->Adj[]
if (d[v] > d[u]+w(u,v))
Note: this
d[v] = d[u]+w(u,v);
is really a
call to Q->DecreaseKey()
What will be the total running time?
Dijkstra’s Algorithm
Dijkstra(G)
for each v V How many times is
ExtractMin() called?
d[v] = ;
d[s] = 0; S = ; Q = V;
while (Q ) How many times is
u = ExtractMin(Q); DecraseKey() called?
S = S U {u};
for each v u->Adj[]
if (d[v] > d[u]+w(u,v))
d[v] = d[u]+w(u,v);
A: O((V+E) lg V) using binary heap for Q
Can acheive O(V lg V + E) with Fibonacci heaps
Dijkstra’s Algorithm
Dijkstra(G)
for each v V
d[v] = ;
d[s] = 0; S = ; Q = V;
while (Q )
u = ExtractMin(Q);
S = S U{u};
for each v u->Adj[]
if (d[v] > d[u]+w(u,v))
d[v] = d[u]+w(u,v);
Correctness: we must show that when u is
removed from Q, it has already converged
Dijkstra’s Algorithm
● If no negative edge weights, we can beat BF
● Similar to breadth-first search
■ Grow a tree gradually, advancing from vertices
taken from a queue
● Also similar to Prim’s algorithm for MST
■ Use a priority queue keyed on d[v]
● Greedy Algorithm
Bellman-Ford Algorithm
BellmanFord()
for each v V Initialize d[], which
d[v] = ; will converge to
shortest-path value
d[s] = 0;
for i=1 to |V|-1
Relaxation:
for each edge (u,v) E Make |V|-1 passes,
Relax(u,v, w(u,v)); relaxing each edge
for each edge (u,v) E
Test for solution
if (d[v] > d[u] + w(u,v))
Under what condition
return “no solution”; do we get a solution?
Relax(u,v,w): if (d[v] > d[u]+w) then d[v]=d[u]+w
Example
u v
5
Each pass relaxes
–2 edges in the order
6 –3 u,v
8 u,y
u,x
z 0 7 v,u
–4
x,v
7 2 x,y
y,v
y,z
9
x y z,u
z,x
Example
u v
5
6 Each pass relaxes
–2 edges in the order
6 –3 u,v
8 u,y
u,x
z 0 7 v,u
–4
x,v
7 2 x,y
y,v
7 y,z
9
x y z,u
z,x
Example
u v
5
6 4 Each pass relaxes
–2 edges in the order
6 –3 u,v
8 u,y
u,x
z 0 7 v,u
–4
x,v
7 2 x,y
y,v
7 2 y,z
9
x y z,u
z,x
Example
u v
5
2 4 Each pass relaxes
–2 edges in the order
6 –3 u,v
8 u,y
u,x
z 0 7 v,u
–4
x,v
7 2 x,y
y,v
7 2 y,z
9
x y z,u
z,x
Example
u v
5
2 4 Each pass relaxes
–2 edges in the order
6 –3 u,v
8 u,y
u,x
z 0 7 v,u
–4
x,v
7 2 x,y
y,v
7 -2 y,z
9
x y z,u
z,x
Another Look
Note: This is essentially dynamic programming.
Let d(i, j) = cost of the shortest path from s to i that is at most j hops.
0 if i = s j = 0
if i s j = 0
d(i, j) =
min({d(k, j–1) + w(k, i): i Adj(k)}
, {d(i, j–1)}) if j > 0
i
z u v x y
1 2 3 4 5
j 0 0
1 0 6 7
2 0 6 4 7 2
3 0 2 4 7 2
4 0 2 4 7 –2
Example
s -1 B
2
A 3 2 E
1
4 -3
C D
5
Bellman-Ford Algorithm
BellmanFord()
What will be the
for each v V
running time?
d[v] = ;
d[s] = 0;
for i=1 to |V|-1
for each edge (u,v) E
Relax(u,v, w(u,v));
for each edge (u,v) E
if (d[v] > d[u] + w(u,v))
return “no solution”;
Relax(u,v,w): if (d[v] > d[u]+w) then d[v]=d[u]+w
Bellman-Ford Algorithm
BellmanFord()
What will be the
for each v V
running time?
d[v] = ;
d[s] = 0; A: O(VE)
for i=1 to |V|-1
for each edge (u,v) E
Relax(u,v, w(u,v));
for each edge (u,v) E
if (d[v] > d[u] + w(u,v))
return “no solution”;
Relax(u,v,w): if (d[v] > d[u]+w) then d[v]=d[u]+w
Converging of shortest paths
● Note that order in which edges are processed affects
how quickly it converges
● After |V|-1 passes, all d values correct
■ Consider shortest path from s to v:
s v1 v2 v3 v4 v
○ Initially, d[s] = 0 is correct, and doesn’t change (Why?)
○ After 1 pass through edges, d[v1] is correct (Why?) and doesn’t
change
○ After 2 passes, d[v2] is correct and doesn’t change
○ …
○ Terminates in |V| - 1 passes: (Why?)
○ What if it doesn’t?
The End