3.5.12 · D5Graphs
Question bank — Floyd-Warshall — all-pairs shortest paths, O(V³)
Before we start, one tiny bit of vocabulary reused everywhere below, so nothing is used before it is named:
True or false — justify
Floyd-Warshall's three loops are symmetric, so any loop order gives the right answer.
False. Only must be outermost; and may swap freely. The DP recurses on , so every pair must fully account for before is unlocked — an inner reads half-updated rows.
Floyd-Warshall works on undirected graphs by treating each edge as two directed edges.
True. Store for each undirected edge; the algorithm never assumes asymmetry. But note: an undirected negative edge is a negative cycle (go back and forth), so negative weights become illegal on undirected graphs.
Floyd-Warshall cannot handle negative edge weights.
False.
min doesn't care about edge sign; negative edges are fine. What it cannot handle is a negative cycle — see Bellman-Ford and Negative Cycles for the distinction.If stays for every after the run, the graph is guaranteed free of negative cycles.
True. A negative cycle through forces ; if no diagonal entry dropped below , no such cheaper-than-staying loop exists.
Running Dijkstra from every vertex is always faster than Floyd-Warshall.
False. For dense graphs () both are near , and Dijkstra breaks on negative edges entirely. Dijkstra-from-all wins only on sparse, non-negative graphs (see Dijkstra's Algorithm).
The in-place single-matrix version can corrupt values because it overwrites the array it reads.
False. In iteration the entries and do not change (they'd only change via ), so reading them mid-sweep is safe.
After Floyd-Warshall finishes, is the shortest path using at most edges.
True (given no negative cycle). A simple shortest path visits each vertex once, so it has edges; unlocking all intermediates captures every such path.
Spot the error
"I put the k loop innermost to keep the intermediate check close to the update — same three loops, same answer."
Error: loop order. Innermost means for a fixed you sweep all before finishing other pairs, so and are still stuck at layer for pairs you haven't reached — you read stale data and mix layers. must be outermost.
"To detect a negative cycle I check whether any edge weight is negative."
Error: edge vs cycle. A single negative edge is harmless. You must check the sum around a loop: after the run, look for . Negative edges are legal; negative cycles are not.
"I initialized like every other pair since there's no self-loop edge."
Error: diagonal base case. The diagonal must start at ("staying put costs nothing"). If it's , the split-at- logic breaks and the negative-cycle test loses its baseline.
"For path reconstruction I set next[i][j] = k whenever I relax through ."
Error: wrong successor. Store
next[i][j] = next[i][k], the first hop toward , not itself. next holds the immediate next vertex; jumping straight to skips the segment ."My graph has a negative cycle, so I'll just read off for pairs not on the cycle — those are still valid."
Error: contamination. Once any , distances for pairs whose shortest path can reach the cycle are meaningless (). You must detect and abort (or use Johnson's Algorithm semantics), not trust the matrix.
"I stored as a large int and got negative distances out of nowhere."
Error: overflow via . Adding two "infinity" sentinels overflows or produces a finite-looking sum that beats a real distance. Guard relaxations with
if d[i][k] < INF and d[k][j] < INF, or use a genuinely unreachable value.Why questions
Why does splitting a -using path into and let both halves use only ?
With no negative cycle, an optimal path visits exactly once; revisiting would form a cycle that only adds cost. So neither half needs as an intermediate — each is a subproblem, and the DP closes on itself.
Why is the negative-cycle test "check the diagonal" rather than tracking cycles explicitly?
starts at (cost of not moving). The only way to make a round-trip cheaper than is a loop whose weights sum below — i.e. a negative cycle through . The diagonal is a free cycle-detector.
Why does Floyd-Warshall beat "Bellman-Ford from every source" on dense graphs?
Bellman-Ford-from-all is ; with that's . Floyd-Warshall is a flat regardless of density, and it's five lines.
Why is Floyd-Warshall and not , given there are layers of a matrix?
The in-place trick reuses one matrix, so each of values of does a single sweep: . We never store separate layers.
Why can't the DP state just be "shortest path from to " without the "" restriction?
Without a restriction there's no smaller subproblem to recurse on — the answer would depend on itself circularly. The -restriction gives a strict ordering ( before ) that makes the recurrence well-founded, the essence of Dynamic Programming.
Why does using min make edge sign irrelevant, unlike Dijkstra's greedy choice?
Floyd-Warshall revisits every pair for every , so a later negative detour can still overwrite an earlier commitment. Dijkstra finalizes a vertex once and never reopens it, which a negative edge can invalidate.
Why is transitive-closure computation (can reach at all?) basically the same algorithm?
Replace / with OR/AND on booleans:
reach[i][j] |= reach[i][k] and reach[k][j]. The "unlock " skeleton is identical — see Transitive Closure.Edge cases
What does Floyd-Warshall output for a completely disconnected graph (no edges)?
The diagonal is and every off-diagonal entry stays — correctly saying "no vertex reaches any other, but each reaches itself at cost ."
What happens if there is a self-loop edge with positive weight?
The diagonal stays because staying put (cost ) always beats taking a positive loop. The self-loop is silently ignored, which is correct.
What happens with a self-loop of negative weight?
That is a negative cycle of length one; drops below and the negative-cycle test fires. Distances become unreliable, as expected.
What is when is reachable from but is not reachable from (directed)?
is finite (a real path exists) while stays . The matrix is asymmetric — Floyd-Warshall respects edge direction.
Single vertex, no edges — does the algorithm still run correctly?
Yes. The matrix is , the sweep changes nothing, output . A valid degenerate case.
Two vertices with edges and (total loop ) — any negative cycle?
No. Both diagonals stay ; a positive round-trip never beats staying put. Negative cycles require the loop sum to be below , not merely the existence of a return edge.
Graph with a zero-weight cycle — is that a negative cycle?
No. A zero-sum loop leaves (equal, not less). "Shortest" is still well-defined; the algorithm treats it as harmless.
If two shortest paths of equal length exist, which does next[i][j] reconstruct?
Whichever relaxation fired first wins, since ties (
<, strict) don't overwrite. The distance is unique; the path reported is implementation-order-dependent but valid.Recall One-line trap summary
Loop order (k outermost), diagonal base case ( not ), negative cycle not negative edge, next[i][j]=next[i][k] not =k, guard against , and never trust the matrix once any .