Held Monday, December 6, 1999
Overview
Today, we consider a more efficient (but less intuitive) solution to
the shortest path problem. This solution is known as Dijrkstra's method.
It shares some ideas with Sierra's proposed solution.
Notes
 Exam 3 due.
 I am revamping the grading policies. It is likely that each exam
will be worth the same as each homework assignment.
 I was going to hand out class evaluations today, but that seems
like a bad idea after hearing your preclass complaints.
Contents
Summary
 Exam 3 due.
 Dijkstra's shortest path algorithm
 Near the end of last class, Sierra suggested that we solve the
shortest path problem by using a priority queue.
 What did he mean by that?
 Let's consider the following undirected graph and find the
shorest path from A to E
GHIJK
 0 1 2 1 
3 20
 1 4 1 9 
ABCDE
   
9 2 0 
   
+F+ 
 6 
++
 A computer scientist named Dijkstra proposed an interesting strategy
for finding the shortest path from A to B.
 He suggested that we can find the shortest path from A
to B by finding the shortest path from A to all nodes in the graph.
(Talk about overkill.)
 His algorithm is generally used with the ``sum of weights'' metric.
 It may also work with selected other metrics.
 His algorithm assumes that edge weights are nonnegative.
 We'll divide the graph into two parts:
 SP.
The nodes whose shortest path we know. For these nodes, we'll store
the distance to that node and the path to that node.
 Est.
The nodes whose shortest path we don't know. For these nodes, we'll
store the shortest known distance to that node (which may not be
the shortest) and the corresponding path.
 Initially, Est contains all the nodes. The
distance from A to itself is 0, and the distance from A to every
other node is some distance greater than the largest distance
in the graph.
 At each step, we'll move one node from Est to SP.
After doing so, we'll update the estimated costs of all of its neighbors.
 Which node to we move? Node s, the one with the smallest
estimated distance.
 Why is this safe? Because the only way to reduce that distance would
be to pick another node, t from Est and have a path
from that node to s such that A to t to s
has smaller distance than our current estimate of the distance form
A to s. But that's not possible, since the cost function
is nondecreasing, and we already know that the cost from A to t
is at least as big as the cost from A to s.
 Note that instead of storing the path, we can simply store the previous
node in the path.
 Dijkstra's algorithm is another example of a greedy algorithm:
at each step in the algorithm, we pick a ``best'' node
 Here's a sample graph to consider. I've used an undirected graph because
the algorithm works equally well for undirected graphs and they're easier
to draw.
G

3
 1 4 1 9
ABCDE
   
9 2 0 
   
+F+ 
 6 
++
 What is the shortest path from A to E? It may be hard to see
at first (not too hard, but nontrivial).
 Let's see what the algorithm tells us.
 Initially,
 SP = {
}
 Est = {
A:(0,empty)
B:(100,?)
C:(100,?)
D:(100,?)
E:(100,?)
F:(100,?)
G:(100,?)
}
 The smallest distance in that graph is the distance to A, so we
 Move A to SP
 Update the distances to all of its neighbors (B, F, and G which now
have actual paths and distances)
 We now have the following information
 SP = {
A:(0,empty)
}
 Est = {
B:(1,A)
G:(3,A)
F:(9,A)
C:(100,?)
D:(100,?)
E:(100,?)
}
 We move B to SP and update its neighbors. We now know a
path to C and a better path to F (A>B>F has cost 1 + 2 = 3).
 SP = {
A:(0,empty)
B:(1,A)
}
 Est = {
F:(3,B)
G:(3,A)
C:(5,B)
D:(100,?)
E:(100,?)
}
 We could then move F or G to SP. Let's say that we move
F. We now know a shorter path to C (A>B>F>C has cost 3, A>B>C
had cost 5) and a path to E.
 SP = {
A:(0,empty)
B:(1,A)
F:(3,B)
}
 Est = {
G:(3,A)
C:(3,F)
E:(9,F)
D:(100,?)
}
 We can then move G or C to SP. Let's say that we move G.
G has no neighbors, so there are no other changes.
 SP = {
A:(0,empty)
B:(1,A)
F:(3,B)
G:(3,A)
}
 Est = {
C:(3,F)
E:(9,F)
D:(100,?)
}
 Next we move C. We can then update the distance to D.
 SP = {
A:(0,empty)
B:(1,A)
F:(3,B)
G:(3,A)
C:(3,F)
}
 Est = {
D:(4,C)
E:(9,F)
}
 We then move D. Note that even though there is an edge from
D to E, it doesn't give us any better path, so we don't change
the entry for E.
 SP = {
A:(0,empty)
B:(1,A)
F:(3,B)
G:(3,A)
C:(3,F)
D:(4,C)
}
 Est = {
E:(9,F)
}
 We move E and we're done
 SP = {
A:(0,empty)
B:(1,A)
F:(3,B)
G:(3,A)
C:(3,F)
D:(4,C)
E:(9,F)
}
 Est = {
}
 What's the shortest path from A to E? It has cost 9 and is the
reverse of (EFBA). How did I get that path? I read it off
from the second elements of SP.
 What's the running time of this algorithm?
 During initialization, we visit each node once, which should be
O(n) in any reasonable implementation.
 In the main loop, we remove each node from Est once, so
there are O(n) repetitions of the main loop.
 We look at each edge twice (one for each node connected to the
edge), so the ``update distances'' part takes O(m) across
the whole algorithm. (m is the number of edges)
 How long does it take to find the smallest distance in Est?
For the structures we've learned, O(n).
 We've find the smallest distance O(n) times.
 So, the running time is O(n^2 + m).
 Since m is O(n^2), the running time is O(n^2).
 That's a significant improvement over the previous algorithm.
 Can we improve it more? In particular, can we speed up the determination
of the smallest distance in Est?
 We might consider using a Heap, since we're doing a lot
of removeSmallest.
 However, we do change priorities of objects, and Heaps aren't
designed to easily support that operation. (How might you support
a
changePriority
method?)
 We'll conclude our discussion of graphs by considering some other
common graph problems and some techniques for solving them.
 You'll note that most of our problems had to do with reachability
and minimization.
 We'll think about some variations.
Tuesday, 10 August 1999
 Created as a blank outline.
Monday, 6 December 1999
 Filled in Dijkstra's algorithm and remaining material.
Back to Shortest Path.
On to History of Computing (1).