Algorithms · Weighted graphs
All-pairs shortest paths: Johnson and Floyd–Warshall
When distances between every pair of vertices are needed, repeating a single-source search is one option. Floyd–Warshall builds the matrix directly; Johnson makes the weights nonnegative and runs Dijkstra from every source.
Prerequisites: Dijkstra, Bellman–Ford and relaxation.
1. The problem
Given a directed weighted graph G = (V, E), we want a matrix D where D[i][j] is the minimum cost from i to j. Its diagonal is 0 when no negative cycle exists; D[i][j] = +∞ when j is unreachable from i. If several edges connect i to j, initialization uses the lightest one.
For one source, start with the preceding guide. For all pairs, graph structure matters: Floyd–Warshall visits every triple of vertices, whereas Johnson takes advantage of sparse edge sets.
2. One graph for both algorithms
Consider four vertices A, B, C, D and the following directed edges. B → C has a negative weight, but cycle B → C → D → B weighs −2 + 2 + 1 = 1: it is not negative.
| A → B | A → C | B → C | B → D | C → D | D → B |
|---|---|---|---|---|---|
| 3 | 8 | −2 | 5 | 2 | 1 |
From A to D, for example, route A → B → C → D weighs 3 − 2 + 2 = 3; A → B → D weighs 8. There is no route from C to A.
3. Floyd–Warshall: allow more intermediates
Number the vertices. D(k)[i][j] is the minimum cost from i to j when only the first k vertices may appear as internal vertices. An optimal route either avoids k or passes through k; in the latter case it combines routes i → k and k → j.
Initialize the diagonal to 0, edges to their weights and all remaining cells to +∞. The loop over k must be outermost: each phase allows exactly one more possible intermediate. Cells may be updated in the same matrix when no negative cycle exists.
for each i, j: D[i][j] = 0 if i = j; otherwise +∞
for each edge i → j of weight w: D[i][j] = min(D[i][j], w)
for each vertex k:
for each vertex i:
for each vertex j:
if D[i][k] and D[k][j] are finite:
D[i][j] = min(D[i][j], D[i][k] + D[k][j])
In the example, allowing B as an intermediate reduces A → C from 8 to 3 + (−2) = 1. Then C reduces A → D from 8 to 1 + 2 = 3. Finally D gives C → B at cost 2 + 1 = 3.
| From / to | A | B | C | D |
|---|---|---|---|---|
| A | 0 | 3 | 1 | 3 |
| B | ∞ | 0 | −2 | 0 |
| C | ∞ | 3 | 0 | 2 |
| D | ∞ | 1 | −1 | 0 |
To reconstruct routes, also store next[i][j], the first vertex after i on the route to j. Initially next[i][j] = j for a direct edge; when going through k improves D[i][j], set next[i][j] = next[i][k].
4. Johnson: reweight and repeat Dijkstra
Johnson suits sparse graphs that may have negative edges but no negative cycles. Add an artificial vertex q and zero-weight edges q → v to every original vertex. Run Bellman–Ford from q: the resulting distance h(v) is a potential. If Bellman–Ford detects a negative cycle, stop.
The inequality follows from Bellman–Ford: h(v) ≤ h(u) + w(u,v). Reweighted edges are therefore suitable for Dijkstra. This adjustment preserves optimal routes: along any route from s to t, intermediate potentials cancel, so the new weight is the original weight plus h(s) − h(t).
add q and zero-weight edges q → v
h = Bellman–Ford(G with q, source q)
if there is a negative cycle: stop
for every edge u → v: w′(u,v) = w(u,v) + h(u) − h(v)
for each original source s:
δ′ = Dijkstra(G with weights w′, source s)
for each reachable t: D[s][t] = δ′(s,t) − h(s) + h(t)
for each unreachable t: D[s][t] = +∞
For the example graph, Bellman–Ford from q gives h(A) = 0, h(B) = 0, h(C) = −2, h(D) = 0. Reweighted edges A → B, A → C, B → C, B → D, C → D, D → B have weights 3, 10, 0, 5, 0, 1 respectively: none is negative.
Dijkstra from A finds δ′(A,C) = 3 via B; restoring the potential gives D[A][C] = 3 − 0 + (−2) = 1. From D it finds δ′(D,C) = 1 via B; the original cost is 1 − 0 + (−2) = −1. These match the Floyd–Warshall matrix.
5. Interactive lab
Edit the edges and compare both algorithms on the same graph. Step through Floyd–Warshall matrix checks, or follow Johnson’s potentials and each Dijkstra search. Choose a pair to see its reconstructed route; distances are provisional during the animation. The lab uses explicit scans for Dijkstra; the complexity table assumes a priority queue.
Distance matrix · rows = sources
Potentials h(v) · Johnson
Reweighted distances from the current source
Selected route
—
- Phase
- —
- Vertex
- —
- Edge
- —
- Result
- —
6. Negative cycles
Floyd–Warshall detects a negative cycle if, at the end, some D[k][k] < 0. For a pair (i, j), the value is −∞ if some such k has finite D[i][k] and D[k][j]: the route can reach the cycle and then j. Checking the diagonal alone does not identify every affected pair.
Johnson finds any negative cycle in the graph because q reaches every vertex. It then does not produce an ordinary finite-distance matrix. If unaffected pairs are needed, use the reachability check through negative cycles after Floyd–Warshall.
In the example, changing D → B from 1 to −1 makes B → C → D → B a cycle of weight −1. A → D becomes −∞; C → A remains +∞ because A cannot be reached from C.
7. Choice and complexity
| Method | When to use it | Time | Memory for the matrix |
|---|---|---|---|
| Floyd–Warshall | Small or dense graphs; simple implementation; analysis of pairs affected by negative cycles | O(|V|³) | O(|V|²) |
| Johnson | Sparse graphs, possibly with negative edges but no negative cycles | O(|V|(|V| + |E|) log |V|) | O(|V|² + |E|) |
| Dijkstra from every vertex | All weights already nonnegative | O(|V|(|V| + |E|) log |V|) | O(|V|² + |E|) |
The Johnson and Dijkstra bounds assume a simple graph, adjacency lists and a binary heap; they include the output matrix. Johnson also runs an initial Bellman–Ford, whose cost is covered by the displayed bound. If rows are consumed one at a time, Johnson’s auxiliary memory drops to O(|V| + |E|). Floyd–Warshall uses O(|V|²) even with a next-vertex matrix.
8. Mistakes and exercises
- Reordering Floyd–Warshall loops: k must remain outermost because it identifies which intermedi are allowed in each phase.
- Running Dijkstra on Johnson’s original negative weights: first reweight edges using the potentials.
- Forgetting the final correction: distances with reweighted edges are not the original distances.
- Confusing +∞ with a negative cycle: it means unreachable; −∞ means the cost is unbounded below.
1. What is D[B][D] in the example, and which route attains it?
It is 0: B → C → D weighs −2 + 2 = 0, versus 5 for the direct edge.
2. With h(B) = 0 and h(C) = −2, what is the reweighted B → C edge?
w′(B,C) = −2 + 0 − (−2) = 0. The potential removes the negative edge weight without changing the optimal route for a fixed pair.
3. After changing D → B to −1, what are the values for A → D and C → A?
A → D is −∞: A can reach the negative cycle and the cycle can reach D. C → A is +∞: no edge leads to A.
4. When can Bellman–Ford be skipped in favor of repeated Dijkstra?
When all original edge weights are nonnegative. No reweighting is needed; each source produces one matrix row.