Floyd-Warshall Algorithm
Computes shortest paths between every pair of nodes in a distance matrix using dynamic programming.
Worth knowing first
#How does it work?
Floyd-Warshall computes shortest paths between every pair of nodes, not just from one start. The result is a V × V distance matrix: dist[i][j] is the cost of the shortest path from i to j.
The idea is dynamic programming: it allows nodes as "stops in between" one at a time. After round k, the best route from i to j using only the first k nodes as stops is known; the new question is whether going via k, dist[i][k] + dist[k][j], beats the current dist[i][j].
The code is just three nested loops, and it handles negative edges too (as long as there is no negative cycle). A negative value on the diagonal means there is a negative cycle.
#Try it yourself
Adjacency list
- 1: 2 (4), 3 (1)
- 2: 1 (4), 4 (5), 5 (2)
- 3: 1 (1), 5 (2), 6 (4)
- 4: 2 (5), 7 (3)
- 5: 2 (2), 3 (2), 7 (6)
- 6: 3 (4), 7 (1)
- 7: 4 (3), 5 (6), 6 (1)
Floyd-Warshall computes the shortest distance for every pair of nodes in a matrix. Each round tries one node k as a stop in between.
#Step by step
- 01Fill the matrix with direct edge weights: 0 on the diagonal, ∞ where there is no edge.
- 02For each node k (the outermost loop):
- 03 for each pair i, j: if dist[i][k] + dist[k][j] < dist[i][j], update dist[i][j].
- 04To rebuild paths, keep a next[i][j] (first stop) table.
#Example code
The same algorithm in 8 languages. Every program is compiled, run and checked to print the same output.
INF = float("inf")
EDGES = [(1, 2, 4), (1, 3, 1), (2, 4, 5), (2, 5, 2), (3, 5, 2), (3, 6, 4), (4, 7, 3), (5, 7, 6), (6, 7, 1)]
N = 7
# dist[i][j] starts as the direct edge weight: 0 on the diagonal, INF where there is no edge.
dist = [[0 if i == j else INF for j in range(N)] for i in range(N)]
for a, b, w in EDGES:
dist[a - 1][b - 1] = dist[b - 1][a - 1] = w # undirected
for k in range(N): # k must be the outermost loop
for i in range(N):
for j in range(N):
if dist[i][k] + dist[k][j] < dist[i][j]:
dist[i][j] = dist[i][k] + dist[k][j]
for row in dist:
print(" ".join(map(str, row)))#Complexity
| Operation | Time |
|---|---|
| Time | O(V³) |
| Memory | O(V²) |
| Reading one pair's distance | O(1) |
| Rebuilding a path | O(V) |
It takes V³ steps no matter how many edges there are. It is very practical for small, dense graphs (a few hundred nodes). For large sparse graphs, running Dijkstra from every node (O(V · E log V)) is faster. The k loop must be the outermost; reordering the loops gives wrong results.
#When to use it?
Whenever distances between all pairs are needed: distance tables between cities, latency between every pair of devices in a network, the transitive closure of a graph (who can reach whom) and precomputed path tables for game maps.
#Practice
Log in to answer questions and save your progress.
Easy
What does Floyd-Warshall compute?
- 1Shortest distances between every pair of nodes
- 2Shortest distances from one start
- 3A minimum spanning tree
- 4A topological order
What is Floyd-Warshall's time complexity?
- 1O(V³)
- 2O(V²)
- 3O(V · E)
- 4O(E log V)
Which of the three loops must be the outermost?
- 1The intermediate node k
- 2The source node i
- 3The target node j
- 4The order doesn't matter
Medium
dist[i][k] = 3, dist[k][j] = 4 and dist[i][j] = 9. What is dist[i][j] after round k?
- 17
- 29
- 33
- 412
Hard
After Floyd-Warshall, what does a negative value on the diagonal (dist[i][i]) mean?
- 1i lies on a negative cycle
- 2i is unreachable
- 3The graph is undirected
- 4Nothing; it is normal