15 Dijkstra
15 Dijkstra
R
S
H
D
P
h
Shortest Path problem (unweighted
graph)
What’s the shortest path from a to a?
- Well….we’re already there.
d
What’s the shortest path from a to b or h?
- Just go on the edge from 0
b
From a to d or c or e?
- Can’t get there directly from a, if we want a length 2 path,
have to go through b or h. s e f
a
From a to f?
c
- Can’t get there directly from a, if we want a length 3 path, have to go through e.
g
big idea for solving shortest paths: If we have all the nodes at distance k away
from the source, then we can check all the outgoing edges from those nodes and get
to all the nodes at distance k + 1 (if we haven’t seen these nodes at k +1 distance
before then we’re just now seeing the shortest path to them)
h
As long as we have all the current vertices at a given distance, we can find the next
distance (by traveling to all the neighbors) and the next distance and the next
distance… until we finally find our target vertex and can stop.
perimeter.add(start);
discovered.add(start);
Changes from traversal BFS: start’s distance = 0;
- Every node now will have an while (!perimeter.isEmpty()) {
Vertex from = perimeter.remove();
associated distance (for convenience)
- Every node V now will have an for (E edge : graph.outgoingEdgesFrom(from)) {
Vertex to = edge.to();
associated predecessor edge that is
if (!discovered.contains(to)) {
the edge that connects V on the to’s distance = from.distance + 1;
shortest path from S to V. The edges to’s predecessorEdge = edge;
that each of the nodes store are the perimeter.add(to);
final result. discovered.add(to)
}
}
} CSE 373 19 SU - ROBBIE WEBER 8
Shortest Path problem d
b
Use BFS to find shortest paths in this graph.
s e f
perimeter.add(start);
a
discovered.add(start); c
start’s distance = 0;
while (!perimeter.isEmpty()) { g
Vertex from = perimeter.remove();
for (E edge : graph.outgoingEdgesFrom(from)) {
Vertex to = edge.to();
if (!discovered.contains(to)) { h
In English:
to’s distance = from.distance + 1;
to’s predecessorEdge = edge;
- starting from the start vertex as the current
perimeter.add(to);
discovered.add(to) node:
} - look at all your undiscovered neighbors and
} record them as distance + 1, and keep track
} of the edge that led to them. Add them to a
queue to be processed
- repeat until we traverse all that can
CSE 373 be- ROBBIE WEBER
19 SU
Shortest Path problem d
b
perimeter.add(start);
while (!perimeter.isEmpty()) { s e f
V from = perimeter.remove(); a
for (E e : graph.outgoingEdgesFrom(from)) {
V to = e.to(); c
if (!discovered.contains(to)) {
edgeTo.put(to, e);
distTo.put(to, distTo(from) + 1);
g
perimeter.add(to);
discovered.add(to)
}
}
} h
return edgeToV;
}
d
b
What about the target vertex?
Shortest Path Problem s e f
a
Given: a directed graph G and vertices
c
s,t
Find: the shortest path from s to t. g
Both BFS modified to find the shortest paths and Dijkstra’s algorithm need to
start computing a shortest path tree in order to find the target.
But if you only care about one target, you can sometimes stop early (in
CSE 373 19 SU - ROBBIE WEBER 12
BFS Shortest Path Summary
- BFS works to find the shortest path summary because BFS traverses the graph
level by level outwards from the start -- because we’re making sure we look at all
the neighbors of all the vertices on the current level, it means that the first time
that we see some vertex u means that we’ve found the shortest path to u. There’s
no way there’s a shorter path because of how comprehensively we’re searching the
graph. (If there were a shorter path, it should have been found at an earlier level!)
slightly more concrete example:
- If you start at level 0, there’s only the start node, and you’ve definitely found the shortest path to that by default (0 edges)
- If you look at the neighbors of the start node who are all at 1 edge/distance away, you’ve definitely found the shortest path to
all of those since they’re just 1 edge length away and it’s not like they could be 0 away.
- If you look at all the neighbors of the nodes who were at 1 edge/distance away, you’re looking at all the nodes who are 2
distance away (when you ignore previously discovered nodes). Since you made sure we were comprehensive about finding all
the nodes at 0 and 1 distance away, the nodes we’re seeing for the first time here must be have 2 as the shortest possible
distance.
- BFS shortest paths keeps track of the actual paths by just keeping track of for
every vertex V, the predecessorEdge that was used to attach V in the SPT. Which
means to trace back a full path you have to loop through all of the
predecessorEdges to go back to the root of the SPT/start vertex.
CSE 373 SP 18 - KASEY CHAMPION 13
BFS Shortest Path Summary
another of way rephrasing this is through invariants:
- because we add vertices to the queue in level order and have the guarantee
that the information in the
when a vertex is added to the queue with its predecessorEdge and distance
recorded, we’ve guaranteed to have found the shortest path /distance to that
vertex
The length of a path in a weighted graph is the sum of the weights along that
path (instead of just counting the # of edges).
1
w x 1
1
s u v t
20 1 1
u
2 u 1
2 s Transform Input t
s t
v
1 v 2 u
Unweighted Shortest
s Paths t 2
v
2 u 1
2 Outputt 2
sTransform
1 v 2
CSE 373 19 SU - ROBBIE WEBER
Weighted Graphs: A Reduction
What is the running time Does our reduction even
of our reduction on this work on this graph?
graph?
5000 u 15 0.5 u 3
s 200 0 t s 𝜋 t
1 v 5000 1 v 500
0
BFS relies on traversing the vertices and Ummm….
edges, so if there are suddenly 5000x more
of each the runtime will get a lot worse.
tl;dr: If your graph’s weights are all small positive integers,
this reduction might work great.
Otherwise we probably need a new idea.
CSE 373 19 SU - ROBBIE WEBER
Weighted Graphs: Take 3
So we can’t just do a reduction.
Instead figure out why BFS worked in the unweighted case,
try to make the same thing happen in the weighted case.
How did we avoid this problem:
1 1 2
w x 1
1
u v t
s
1 1
0 20 3 21 22
u v t
s
Idea: what if we copy the level-by-level idea but instead traverse distance-by-distance?
CSE 373 19 SU - ROBBIE WEBER
Weighted Graphs: Take 3 -Visiting nodes in
distance-order (should seem similar to BFS still)
1
1
w x
1
u v t
s
1 1
6
- One way to think about our new algorithm: imagine that every edge weight represents the distance it takes to
traverse that edge, and that we’ll simulate the order of traversal by trying to explore all of our outgoing edges at
the same time but with respect to the edge weight distances.
- Say we start at search at s and want to traverse to our neighbors 1 distance/time away: since we’re thinking of
this process traversing in all possible directions, how far do we get? Well S W is only distance 1, so we actually
get to W. The S U edge that we know about is distance 6, so even though we started traversing it, we only get
1/6 of the way through that edge.
- Say another unit of time passes in our constant traversal and we traverse 1 more distance in all the directions,
and now the upper path has traversed WX (total distance from S is 2), and meanwhile S U is only 2/6 done.
- Say another unit of time passes and we get to U through XU (total dist from S is 3), and SU is 3/6 done.
This order of processing nodes guarantees that when we finally reach a node U (with the constant rate of travel
idea) we’ve guaranteed we found the shortest path to it (just like BFS if there were a shorter path, we would’ve
gotten here sooner since we’re exploring all the paths simultaneously).
Overall they’re really similar and Dijkstra’s just has a few more steps than BFS,
so if you’re confused, start with understanding BFS shortest paths and then
after you feel comfortable with that, tackle practicing / understanding
Dijktra’s.