Pattern #60
Floyd-Warshall Algorithm
All-pairs shortest paths, intermediate-node matrix DP, correct loop order, negative cycles, path reconstruction, closure variants, and Go templates.
Must Solve
10 core questions — solve these first.
- 1.Floyd-Warshall All-Pairs Shortest PathMatrix DP with k as outer loopmedium
- 2.Find the City With the Smallest Number of NeighborsCount threshold-reachable nodes after preprocessingmedium
- 3.Shortest Distance Between Every Pair of NodesDirect lookup after O(V³) workmedium
- 4.Detect Negative Cycle Using Floyd-WarshallCheck for a negative diagonalmedium
- 5.Transitive Closure / ReachabilityReplace min-plus with boolean OR-ANDmedium
- 6.Minimum Cost Between All PairsInitialize direct edges and run matrix DPmedium
- 7.Shortest Path in Weighted Matrix GraphMatrix input maps directly to distmedium
- 8.All-Pairs Shortest Path with Negative EdgesWorks unless affected by a negative cyclehard
- 9.Reconstruct Shortest Paths Between All PairsMaintain next or predecessor matrixhard
- 10.Find Minimum Cycle Cost — Related VariantCombine paths and closing edges carefullyhard
Also Important
8 closure and advanced variants.
- 11.Evaluate Division — Closure ThinkingCombine pair relations through intermediatesmedium
- 12.Course Prerequisite ReachabilityBoolean transitive closuremedium
- 13.Network Reachability Between Every PairPrecompute all reachability queriesmedium
- 14.Minimum Distance QueriesO(1) answer after preprocessingmedium
- 15.Boolean Floyd-Warshall / Warshall AlgorithmReachability rather than distancemedium
- 16.Minimax Path VariantsReplace + with max and minimize resulthard
- 17.Maximum Product / Probability ClosureChange the algebra to maximize producthard
- 18.Johnson's Algorithm — Advanced ComparisonBetter option for sparse all-pairs graphshard
How to Think
Floyd-WarshallMatrix DPAllowed, but inspect negative cyclesAnswer dist[u][v] in O(1)For every intermediate k:
For every source i:
For every target j:
try route i → k → jGo Quick Reference — Matrix DP
func floydWarshall(dist [][]int64) [][]int64 {
n := len(dist)
// Before calling: diagonal = 0 and missing edges = INF.
for k := 0; k < n; k++ { // k MUST be outermost
for i := 0; i < n; i++ {
if dist[i][k] == INF { continue }
for j := 0; j < n; j++ {
if dist[k][j] == INF { continue }
candidate := dist[i][k] + dist[k][j]
if candidate < dist[i][j] {
dist[i][j] = candidate
}
}
}
}
return dist
}After processing k, dist[i][j] is the best path whose intermediate nodes come only from the processed set.
Variants & Path Reconstruction
Negative cycle
After completion, dist[v][v] < 0 identifies a node on a negative cycle.
Actual path
Maintain next[i][j]; when i→k→j improves, set next[i][j] = next[i][k].
Transitive closure
Use reachable[i][j] = reachable[i][j] || (reachable[i][k] && reachable[k][j]).
Minimax path
Use min(current, max(leftPart, rightPart)) instead of the usual min-plus formula.
Multiple edges
Initialize dist[u][v] with the minimum among parallel edge weights.
Directed graph
Set only dist[u][v]; for undirected graphs also set dist[v][u].
Matrix [i][j] → best i-to-j cost
k → newly allowed middle node
Update → min(direct, i→k + k→j)
Loop order → k, i, j
Negative cycle → negative diagonalComplexity
Time: O(V³)
Distance space: O(V²)
Path matrix: O(V²)
Query afterward: O(1)Excellent for modest dense graphs or many pair queries; avoid it when V is huge and the graph is sparse.
Common Interview Mistakes
• Using the wrong loop order—k must be outermost
• Forgetting dist[i][i] = 0
• Adding INF values and overflowing
• Ignoring negative diagonal cycle detection
• Using O(V³) on an enormous sparse graph
• Overwriting a cheaper parallel edge
• Confusing all-pairs with one-source shortest path
Interview Rules
All pairs → Floyd-Warshall
State → dist[i][j]
Transition → min(direct, through k)
Loop order → k, then i, then j
Diagonal → 0 initially
Negative cycle → dist[v][v] < 0
Actual paths → next matrix
Huge sparse graph → repeated Dijkstra / JohnsonProduction Thinking
Routing tables → precompute all-pairs costs when the network is modest and queries are frequent.
Service reachability → boolean closure answers whether any dependency chain exists.
Production warning → O(V³) time and O(V²) memory become impractical quickly.
Remember This
Floyd-Warshall → all pairs
State → dist[i][j]
Middle node → k
Loop order → k, i, j
Missing path → INF guard
Negative cycle → dist[v][v] < 0
Time → O(V³)💡 Golden Rule: Let each node become an allowed intermediate, one at a time, and improve every source-target pair through it.