Introduction
The all-pairs shortest-paths problem asks for for every pair of vertices. Running a single-source algorithm from each vertex works when weights are nonnegative (Dijkstra times) or in general (Bellman-Ford times), but the classical GATE algorithm is Floyd-Warshall: a DP that allows negative weights and detects negative cycles by inspecting the diagonal.
Prerequisites
- Single-Source Shortest Paths: relaxation, negative cycles, when Dijkstra applies.
- Dynamic Programming Fundamentals: bottom-up table fill.
Core concepts
DP state
Number vertices . Let be the shortest-path weight from to using only intermediate vertices in .
The answer is . Space suffices by overwriting a single matrix in place.
Negative cycles
Some final diagonal entry is negative if and only if the graph contains a negative cycle. Here a cycle is simple (no repeated vertices apart from its endpoints), while a closed walk may repeat vertices. A negative diagonal entry at certifies a negative closed walk through , not necessarily a negative simple cycle containing . A zero diagonal does not certify an unaffected source: the walk distance from to is unbounded below whenever can reach a negative cycle that can reach . The finite matrix entries are not shortest-walk distances for those affected pairs.
Transitive closure
Replacing and by and on a boolean adjacency matrix yields the reachability (transitive closure) matrix in the same loops: , with when or . CLRS presents this in Section 25.2. For the four-vertex example below every vertex reaches every other, so the closure is all ones. Delete the edge , the only edge into vertex 1, and column 1 of the closure becomes : only vertex 1 itself reaches 1.
Algorithms and pseudocode
Pseudocode uses 1-based matrices and <- for assignment.
FLOYD-WARSHALL(W)
1 n <- W.rows
2 D^(0) <- W
3 for k <- 1 to n
4 let D^(k) be a new n x n matrix
5 for i <- 1 to n
6 for j <- 1 to n
7 D^(k)[i,j] <- min(D^(k-1)[i,j], D^(k-1)[i,k] + D^(k-1)[k,j])
8 return D^(n)In-place variant. Drop the superscripts and update D[i,j] in the triple loop; the algorithm remains correct (CLRS Exercise 25.2-4).
The loop over must be outermost. The recurrence needs every entry of level before level starts. Writing the loops as for i, for j, for k (with innermost) computes each once, from entries that may not be final yet. Counterexample: the path with every weight 1. With innermost, is computed while is still (column 3 comes before column 4), and no later step revisits . It ends at instead of 3. With outermost the answer is 3.
Time / space. time, space. Independent of the number of edges, so dense graphs are the natural fit. For sparse nonnegative graphs, Dijkstra runs in can be faster.
Reconstruction. Keep a predecessor matrix : initially if and NIL otherwise; when the path through improves , set . Recursively print the path from to then the edge to . In the example below, and , so the path is of weight .
Edge cases. Missing edges start as ; . Initialize off-diagonal to the minimum weight among direct edges from to , or if none exists. Initialize , interpreting a missing self-loop as . A negative self-loop must be retained; it is already a negative cycle.
Mathematical explanation
Optimal substructure
A shortest path that uses intermediate vertices from either avoids entirely (then it equals the answer) or splits as a shortest path and a shortest path, both using intermediates from . Those are the only two options, justifying the recurrence.
Comparison with repeated single-source
| Method | Weights | Time (adj. lists / matrix) |
|---|---|---|
| Dijkstra (binary heap) | nonnegative | |
| Bellman-Ford | arbitrary | |
| Floyd-Warshall | arbitrary | |
| Johnson (related material) | arbitrary, no neg. cycle | with Fib. heaps |
Johnson's algorithm reweights by a Bellman-Ford potential then runs Dijkstra from every vertex; it is the sparse-graph alternative when negatives appear but no negative cycle exists.
Worked examples
Four-vertex run
Weight matrix ( on the diagonal, written as inf):
After (through vertex 1): stays 4; does not improve. After : becomes , becomes . After : becomes , becomes . After : becomes , becomes . Final matrix:
All diagonal entries are 0, so no negative cycle.

Negative cycle on the diagonal
Change from to . The cycle has weight . After round , , and are negative (vertex 2 lies on the cycle of weight ). stays 0: every cycle through vertex 3 has positive weight, even though 3 can reach a negative cycle. A zero diagonal entry does not rule out reaching a negative cycle; it does not rule out a negative closed walk through the vertex, obtained by repeating a reachable negative cycle sufficiently often and returning.
In-place update subtlety
When the triple loop updates in place, the right-hand side reads and . These two entries do not change during round : , and when there is no negative cycle, so row and column are the same at levels and . Overwriting one matrix is therefore exactly as good as keeping two. The same in-place trick is not safe for every DP; matrix-chain multiplication, for example, needs the strict length order.
Space and early termination
Floyd-Warshall offers no useful early termination: even if a round leaves the matrix unchanged, later values can still improve entries. Space is for distances plus if a full predecessor matrix is stored. For a single pair query on a sparse nonnegative graph, a bidirectional Dijkstra is preferable; Floyd-Warshall earns its keep when many pairs are needed or when negatives appear without a cycle.
Important properties and observations
- Floyd-Warshall always runs in whether the graph is sparse or dense: the update line runs exactly times (64 for ).
- Matrix-multiplication view is different (CLRS Section 25.1): allows paths of at most edges and is built with a min-plus "product". Repeated squaring needs products, in total. Floyd-Warshall instead indexes by the set of allowed intermediate vertices and reaches .
- Johnson's algorithm (related material, CLRS Section 25.3): add a new vertex with 0-weight edges to all vertices, run Bellman-Ford from it to get , reweight by , then run Dijkstra from every vertex and undo the reweighting.
- The algorithm does not early-exit; even if the graph is a DAG the loops still execute fully (the DAG single-source method is better for one source).
- Order of inside the loop does not matter for the in-place version's correctness on distances.
- Common misconceptions.
- "Floyd-Warshall requires nonnegative weights." False; it is designed for negatives (and reports cycles).
- "A zero on the diagonal always means no cycle." A zero is normal (empty path); a negative diagonal entry means a negative cycle.
- "The algorithm lists the paths." Distances yes; paths need the predecessor matrix.
GATE examination perspective
- FILL ONE ENTRY. Compute from the recurrence with a partially filled matrix. First identify the largest already applied, so the recurrence is used at the right level.
- LOOP ORDER. must be the outermost loop; a code fragment with innermost is wrong (path example).
- NEGATIVE CYCLE. Read the diagonal after : a negative certifies a negative closed walk through . Some diagonal is negative iff a negative cycle exists; it need not be a simple cycle through every such .
- TRANSITIVE CLOSURE. Same loops with OR and AND; by convention.
- COMPLEXITY. , independent of ; exactly executions of the update line.
- CHOOSE VERSUS DIJKSTRA. Dense or negative weights: Floyd-Warshall; sparse and nonnegative: repeated Dijkstra; sparse with negatives but no negative cycle: Johnson.
- PATHS. Distances alone do not give the path; use and update it exactly when the distance improves.
Summary
Sources
- T. H. Cormen, C. E. Leiserson, R. L. Rivest, C. Stein, Introduction to Algorithms, 3rd ed., MIT Press, 2009, Chapter 25, Sections 25.1 (shortest paths and matrix multiplication), 25.2 (Floyd-Warshall, including transitive closure) and 25.3 (Johnson's algorithm); Exercises 25.2-4 (in-place update) and 25.2-6 (negative-cycle detection).