Shortest Paths
A related problem to minimum spanning trees is shortest paths. That is, what is the shortest path between two vertices in a graph, say and . A naive greedy approach seems compelling given our exploration of minimum spanning trees. For example, consider the following graph:

Suppose we want to find the shortest path from to . We could try to start from , and choose the edge with the least weight to traverse next, eventually arriving at . However, this yields the path which has total weight . The optimal path instead is the top path of the graph: with total weight . Note that even if we were to divine that it is better to go to from , we encounter the same problem at : a greedy choice will send us down to (at cost 4) when traversing would have been the correct move!
More generally, this approach has the problem where it may send us down a sub-optimal path:

For example, we may reach vertex in the graph above only to find that we are either in a sub-optimal path or worse yet, that the target node of our path is unreachable from ! In this case, we would be forced to backtrack to explore other possible paths. In general, this occurs when a greedy choice fails: we have to "undo" our optimal choice and try other possibilities instead. We may end up exploring all such possibilities exhaustively which is problematic if there are many possibilities to consider! This realization might motivate us to dismiss any sort of greedy algorithm for this problem. However, if we are smart in tracking enough information so that we never need to backtrack, we can retain a greedy approach!
The algorithm we'll consider is Dijkstra's algorithm which we can think of as a refinement of Prim's algorithm for minimal path searching. Note that Prim's proceeded by growing a minimal spanning tree from a single node. Dijkstra's proceeds similarly, growing an optimal path from the start vertex under consideration. However, unlike Prim's which only tracks the growing MST of interest, Dijkstra's does not just record the current optimal path to the desired end vertex but all such optimal paths to every vertex in the graph from the start vertex. This additional information is sufficient for us to make greedy choices that always lead to the discovery of the optimal path.
Suppose we are interested in finding the shortest path from to in our example graph for this section. Dijkstra's ultimately tracks the shortest path from through the nodes it has visited so far to all nodes in the graph, refining these paths as it greedily consumes vertices in the graph. Initially, we know that the shortest path from to itself is simply staying at for a cost of 0. For every other node, we don't know a path---indeed, such a path may not exist!---so we assign the value to these paths.
| Destination | Path | Cost |
|---|---|---|
| 0 | ||
| ? | ||
| ? | ||
| ? | ||
| ? | ||
| ? |
We begin by considering and its edges. We look at each edge incident to and update our table based on these edges. When looking at these edges, we ask the question:
Can taking this edge to a vertex give us a new optimal path from to ?
There are two such edges to consider: and . Since we don't know of any paths from to either of these edge's endpoints---represented by the fact that their entries in the table are ---we can update our shortest paths entries for these vertices with these edges.
| Destination | Path | Cost |
|---|---|---|
| 0 | ||
| ? | ||
| ? | ||
| ? |
After processing these edges, we are done with . An invariant of the algorithm is that we never need to reconsider these edges again. The important information about them has been recorded in the table, allowing us to avoid backtracking if an optimal path needs to be updated!
We now repeat the process by choosing a vertex that we have not yet visited and updating the table based on its incident edges that we have not yet considered. Which vertex do we consider next? This is where we'll make our greedy choice: we'll consider the vertex with minimum cost according to the table that we have not yet visited.
In our running example, this is node with current path cost . We now update our table with 's additional edge: . Note that this edge gives us a path from to ; what is its length? It is the length of the optimal path from to plus the cost of traversing ! This quantity is corresponding to the path .
| Destination | Path | Cost |
|---|---|---|
| 0 | ||
| ? | ||
| ? |
Next we consider node since its current shortest path cost is lower than 's cost . We thus consider edges and next. Edge updates the path to as expected. However, edge introduces a choice between two paths:
- The current shortest path in the table: with cost .
- The candidate shortest path through . The cost of this path is the minimal cost of reaching from plus the cost of traversing : .
We note that and thus the candidate path is shorter than our current best known path. We therefore update the table to reflect the fact, recording a new best shortest path for !
| Destination | Path | Cost |
|---|---|---|
| 0 | ||
| ? |
We next consider with current shortest path length . It has one unvisited incident edge, , allowing us to final reach our intended endpoint, , with cost .
| Destination | Path | Cost |
|---|---|---|
| 0 | ||
Now we will consider vertex with edge . We employ the same logic here as with . We need to compare the:
- The current shortest path recorded in the table: of length .
- The candidate shortest path through : of length .
The candidate shortest path is shorter, so we update the table with the new path for .
| Destination | Path | Cost |
|---|---|---|
| 0 | ||
Since has no unvisited edges to process, we don't need to do anything to process it, completing the search procedure. We can now inspect the table to find the shortest path from to , which is of length as desired!
With this example, we see that the salient parts of Dijkstra's algorithm are:
- Repeatedly choosing vertices to process based on their current, best-known shortest paths from the start vertex.
- Comparing our current known shortest paths with paths through the current vertex under consideration and choosing the better of the two.
Let be an undirected graph. Suppose that we are interested in finding all shortest paths starting from vertex . Let be the cost of the shortest known path from to . Dijkstra's algorithm proceeds as follows:
-
Initially, let and for all that are not .
-
Repeatedly choose vertex that has minimal among all vertices that have not yet been processed in .
-
For each edge that has not yet been processed by the algorithm, update the shortest known path to as follows:
-
After Dijkstra's algorithm completes, records the shortest path from to in for all .
Note that our choice of initially assigning unknown paths the value makes the description of our algorithm concise. We don't need to define a special case for when we first find a path to a target vertex. We will always choose the found path because is effectively larger than the length of any known path length we would consider during execution of the algorithm.