Shortest Paths

Shortest paths as one relaxation invariant expressed through BFS, DAG order, Dijkstra, Bellman–Ford, Floyd–Warshall, and Johnson—with precise weight preconditions and negative-cycle semantics.

A shortest-path algorithm does not merely “pick the smallest edge.” It maintains path-backed upper bounds on unknown distances and improves them through relaxation. BFS, topological-order processing, Dijkstra, Bellman–Ford, and all-pairs dynamic programming differ mainly in which relaxation order is safe—and that safety comes from explicit graph and weight preconditions.

The most damaging mistakes are therefore contract mistakes: running Dijkstra with a negative edge, treating no edge as weight zero, declaring every query invalid because of an unreachable negative cycle, or reconstructing a path from stale predecessors. This entry develops the proofs that make those failures visible.

Define the optimization problem first #

Let G=(V,E)G=(V,E) be a directed graph with additive edge weights

w:E→R.w:E\to\mathbb R.

A walk P=(v0,v1,…,vk)P=(v_0,v_1,\ldots,v_k) follows an edge (vi−1,vi)(v_{i-1},v_i) at each step and has weight

w(P)=∑i=1kw(vi−1,vi).w(P)=\sum_{i=1}^{k}w(v_{i-1},v_i).

A path has no repeated vertices under the convention used here. Algorithms may manipulate walks, but when a finite optimum exists without a relevant negative cycle, there is a simple shortest representative: deleting a nonnegative repeated cycle cannot increase cost.

For source ss, the distance to vv is

δ(s,v)=inf⁡{w(P):P is an s-to-v walk}.\delta(s,v)=\inf\{w(P):P\text{ is an }s\text{-to-}v\text{ walk}\}.

Three outcomes must stay distinct:

  • unreachable: no walk exists, so δ(s,v)=+∞\delta(s,v)=+\infty;
  • finite optimum: at least one shortest path realizes a real-valued distance;
  • unbounded below: reachable negative cycling can make walk costs arbitrarily small, so δ(s,v)=−∞\delta(s,v)=-\infty for affected targets and no finite shortest walk exists.

Direction matters. A path may use only the direction of its edges. Weights need not be geometric lengths: they may be any additive cost for which the algorithm’s comparison and arithmetic assumptions hold.

Optimal substructure and relaxation #

If a subpath of a shortest path were not shortest between its own endpoints, replacing it with a cheaper subpath would make the full path cheaper. This optimal substructure makes local improvement meaningful.

Maintain a tentative label d[v]d[v] and predecessor parent[v]parent[v]:

d[s]=0,d[v]=+∞(v≠s).d[s]=0, \qquad d[v]=+\infty\quad(v\ne s).

Relax directed edge (u,v)(u,v) by checking

d[v]>d[u]+w(u,v).(1)d[v] > d[u] + w(u,v). \tag{1}

If true, assign

d[v]←d[u]+w(u,v),parent[v]←u.(2)d[v]\leftarrow d[u]+w(u,v), \qquad parent[v]\leftarrow u. \tag{2}

Do not add a weight to infinity in an implementation: first require that d[u]d[u] is finite, or use arithmetic with a safe mathematical infinity.

The path-backed upper-bound invariant #

Initially, d[s]=0d[s]=0 is backed by the empty path and every other label is infinity. A successful relaxation extends the concrete path backing d[u]d[u] with real edge (u,v)(u,v). Therefore every finite label remains the weight of an actual source-to-vertex walk. Whenever a finite optimum exists,

d[v]≥δ(s,v).d[v]\ge\delta(s,v).

Relaxation can lower an overestimate; it cannot invent a value below the true optimum while the label remains path-backed. This is the central debugging invariant. If a reported distance has no predecessor path with the same edge sum, the implementation is inconsistent even if the number looks plausible.

At an optimum, every reachable edge obeys a triangle inequality:

δ(s,v)≤δ(s,u)+w(u,v).\delta(s,v)\le\delta(s,u)+w(u,v).

Algorithms differ in how they reach a state where all relevant inequalities are satisfied and when a tentative label may be declared final.

Select by graph and weight preconditions #

Condition Scope Method Governing reason
Every edge has the same nonnegative cost SSSP BFS FIFO processes increasing edge-count layers
Directed acyclic graph; weights may be negative SSSP topological relaxation every predecessor is processed before its target
General graph; all weights nonnegative SSSP Dijkstra minimum tentative label can be settled permanently
Negative edges allowed; no source-reachable improving cycle SSSP Bellman–Ford repeated passes cover paths by edge count
No relevant negative cycle when finite distances are required; dense or matrix-oriented workload APSP Floyd–Warshall dynamic program over allowed intermediate vertices
Sparse graph; negative edges but no negative cycle APSP Johnson reweight once, then run nonnegative SSSP per source

This is a correctness table first, not a universal speed ranking. Actual complexity also depends on graph representation, priority queue, graph density, and requested output.

Equal weights reduce to BFS #

When every edge has the same cost c≥0c\ge 0, BFS still gives an optimum: if c>0c>0, minimizing weight is the same as minimizing edge count, while if c=0c=0, every reachable walk has weight zero. BFS proves that its first discovery of vv gives the minimum number of edges from ss; multiplying that layer number by cc gives the shortest-path distance.

This article does not repeat the queue proof. The bridge is relaxation: a BFS discovery assigns d[v]=d[u]+1d[v]=d[u]+1, and FIFO order ensures no later relaxation can improve it. Once weights differ, layer order no longer orders path cost, so FIFO alone loses its correctness argument.

DAG shortest paths: one safe pass #

In a directed acyclic graph, compute a topological order v1,…,vnv_1,\ldots,v_n and relax every outgoing edge of each vertex in that order. Negative edges are allowed because no edge returns to an already processed predecessor position.

Correctness is induction on the topological order. Before processing viv_i, every path into viv_i ends with an edge from some earlier vertex. By the induction hypothesis those predecessor distances are final, and their outgoing edges have been relaxed. Thus every possible final edge into viv_i has already offered its candidate, so d[vi]=δ(s,vi)d[v_i]=\delta(s,v_i). Relaxing its outgoing edges establishes the candidates needed later.

The cost is Θ(V+E)\Theta(V+E) with adjacency iteration: one topological traversal plus one relaxation per edge. Applying the same one-pass idea to a cyclic graph has no proof; a later edge may improve a vertex whose outgoing edges were already processed.

Dijkstra: settle the minimum label #

Dijkstra’s label-setting algorithm assumes

w(e)≥0for every edge e.w(e)\ge 0\qquad\text{for every edge }e.

Maintain a settled set SS and a min-priority queue keyed by tentative distance:

  1. initialize labels and enqueue the source;
  2. extract an unsettled vertex uu with minimum tentative label;
  3. settle uu—its label is now final;
  4. relax every outgoing edge (u,v)(u,v) and update the queue;
  5. repeat until the queue has no finite candidate.

Zero-weight edges are valid. Negative edges are what break the proof.

Why the minimum tentative label is final #

Suppose uu is the first vertex Dijkstra settles incorrectly. Take a shortest path from ss to uu and let yy be its first unsettled vertex at that moment; let xx precede yy, so xx is settled. When xx was processed, relaxing (x,y)(x,y) ensured

d[y]≤δ(s,x)+w(x,y)=δ(s,y).d[y]\le\delta(s,x)+w(x,y)=\delta(s,y).

The path-backed invariant also gives d[y]≥δ(s,y)d[y]\ge\delta(s,y), hence d[y]=δ(s,y)d[y]=\delta(s,y). Because the remaining suffix from yy to uu has nonnegative weight,

d[y]=δ(s,y)≤δ(s,u)<d[u].d[y]=\delta(s,y)\le\delta(s,u)<d[u].

But uu was extracted with the minimum tentative label, so d[u]≤d[y]d[u]\le d[y]—a contradiction. The nonnegative suffix is the exact point where the precondition enters.

Trace with duplicate queue entries #

Use edges

S→A(4), S→B(1), B→A(2), A→C(1), B→C(5), C→T(3), A→T(7).S\to A(4),\ S\to B(1),\ B\to A(2),\ A\to C(1),\ B\to C(5),\ C\to T(3),\ A\to T(7).

Extracted current entry Successful relaxations Current finite labels
S:0 A←4, B←1 A=4, B=1
B:1 A←3, C←6 A=3, C=6
A:3 C←4, T←10 C=4, T=10
stale A:4 skip unchanged
C:4 T←7 T=7
stale C:6 skip unchanged
T:7 none final

If the priority queue cannot decrease a key in place, push the improved pair again. On extraction, discard (u,key) when key != d[u] or uu is already settled. Without that stale-entry check, obsolete work can trigger repeated scans or incorrect callback behavior.

The predecessor chain gives

S→B→A→C→TS\to B\to A\to C\to T

with cost 1+2+1+3=71+2+1+3=7, exactly matching d[T]d[T].

Complexity depends on both structures #

With adjacency lists and a binary heap, each vertex is extracted and each edge can cause a logarithmic queue update, giving

O((V+E)log⁡V).O((V+E)\log V).

For a reachable connected-scale graph this is often abbreviated O(Elog⁡V)O(E\log V), but the assumptions should be stated. With a dense matrix and a simple array scan for the smallest unsettled label, Dijkstra takes O(V2)O(V^2). A different heap changes asymptotic queue operations and constant factors; there is no representation-free runtime.

Stopping a single-target query is safe when the target is extracted and settled, not merely when an edge first gives it a finite label.

The negative-edge counterexample #

Consider this directed graph:

After processing S, Dijkstra has A=2 and B=5. It settles A, assigns T=4, and may settle T before B. But the true best route is

S→B→A→TS\to B\to A\to T

with cost 5−4+2=35-4+2=3. Edge B→A(-4) crosses back into the settled region and makes the previously final label smaller. A particular negative-edge graph may coincidentally produce a correct run; the issue is that the label-setting algorithm has no correctness guarantee.

Bellman–Ford: correctness by edge count #

Bellman–Ford repeatedly relaxes every edge. Its proof tracks how many edges an optimal candidate may use.

In a clean dynamic-programming formulation, let di[v]d_i[v] be the minimum weight of an ss-to-vv walk using at most ii edges. Then

di[v]=min⁡(di−1[v],min⁡(u,v)∈E(di−1[u]+w(u,v))).(3)d_i[v]=\min\left( d_{i-1}[v], \min_{(u,v)\in E}\bigl(d_{i-1}[u]+w(u,v)\bigr) \right). \tag{3}

An in-place implementation may propagate farther within one pass depending on edge order, but after pass ii it has found at least every optimum with at most ii edges. Edge order can accelerate convergence; correctness does not depend on favorable order.

If a finite shortest path exists and no source-reachable negative cycle can improve it, choose a simple shortest path. It has at most V−1V-1 edges. Therefore V−1V-1 complete passes suffice. A pass with no successful relaxation permits safe early termination because every edge inequality is already satisfied.

Worst-case time with an edge list is

O(VE),O(VE),

with O(V)O(V) auxiliary distance/predecessor storage beyond the graph.

Stage-by-stage example #

Use edges

S→A(4), S→B(5), A→C(3), B→C(−4), C→T(2), A→T(8).S\to A(4),\ S\to B(5),\ A\to C(3),\ B\to C(-4),\ C\to T(2),\ A\to T(8).

The conceptual DP stages are:

Maximum edges SS AA BB CC TT
0 0 ∞\infty ∞\infty ∞\infty ∞\infty
1 0 4 5 ∞\infty ∞\infty
2 0 4 5 1 12
3 0 4 5 1 3

At two edges, B→C(-4) improves C to 1. At three, C→T(2) improves T to 3. The predecessor certificate is S→B→C→TS\to B\to C\to T.

Negative cycles are scoped, not global #

After the V−1V-1 simple-path bound, perform one more full edge scan. If a reachable edge can still improve a label, some improving walk repeats a vertex; the repeated segment contains a negative cycle. Predecessor links can be used to enter and extract a cycle witness: step backward VV times from an improved vertex to guarantee arrival inside the repeated region, then follow predecessors until a vertex repeats.

In the example, add C→A(-4). The cycle

A→C→AA\to C\to A

has weight 3−4=−13-4=-1. It is reachable from S, so repeatedly traversing it lowers costs to A, C, and any vertex reachable afterward, including T.

The effect is not “all answers everywhere are invalid.” For a source-specific query:

  1. the cycle must be reachable from the source to affect any source label;
  2. a target must be reachable from that cycle to have distance −∞-\infty;
  3. an unreachable negative cycle in another component does not alter finite source distances.

An API may throw on detecting any source-reachable negative cycle, return the cycle, or propagate −∞-\infty only to affected vertices. State which contract is in force.

For an undirected weighted graph represented by traversable incidences in both directions, a reachable negative edge {u,v}\{u,v\} creates the closed walk u→v→uu\to v\to u with twice the negative weight. Under walk semantics this is a negative cycle. A problem restricted to simple paths is a different optimization problem and must not inherit the walk-based theorem silently.

Floyd–Warshall: all pairs by allowed intermediates #

Floyd–Warshall solves APSP with a dynamic program and can also expose negative cycles. For the finite-distance recurrence, fix a pair not affected by a negative cycle and number the vertices 1,…,n1,\ldots,n. Let

D(k)[i,j]D^{(k)}[i,j]

be the minimum weight of an ii-to-jj walk whose intermediate vertices are drawn only from {1,…,k}\{1,\ldots,k\}. A best route either avoids vertex kk or passes through it:

D(k)[i,j]=min⁡(D(k−1)[i,j],D(k−1)[i,k]+D(k−1)[k,j]).(4)D^{(k)}[i,j] =\min\left( D^{(k-1)}[i,j], D^{(k-1)}[i,k]+D^{(k-1)}[k,j] \right). \tag{4}

Initialize every entry to +∞+\infty, then set

D(0)[i,i]←min⁡(D(0)[i,i],0)D^{(0)}[i,i]\leftarrow\min(D^{(0)}[i,i],0)

for every vertex and, for every edge (u,v)(u,v), set

D(0)[u,v]←min⁡(D(0)[u,v],w(u,v)).D^{(0)}[u,v]\leftarrow \min(D^{(0)}[u,v],w(u,v)).

The minimum operations preserve the lightest parallel edge and also preserve a negative self-loop instead of overwriting it with zero.

There are nn stages, each inspecting n2n^2 ordered pairs, so time is Θ(V3)\Theta(V^3) and distance storage is Θ(V2)\Theta(V^2). The recurrence represents finite shortest distances only when no negative cycle can affect the pair under consideration. A next-hop or predecessor matrix supports path reconstruction but has its own update orientation.

For a concrete recurrence, take edges P→Q(3), P→S(10), Q→R(-2), Q→S(8), and R→S(4). Before allowing R, the best known P→S cost is 10. Because P→R costs 3−2=13-2=1, stage R tests

min⁡(10, 1+4)=5\min(10,\ 1+4)=5

and records the route P→Q→R→S.

If after all stages D[i,i]<0D[i,i]<0, there is a negative closed walk from ii back to ii; equivalently, ii can reach a negative cycle that can return to ii. The diagonal is therefore a detection signal, not a finite shortest distance. Ordinary finite APSP values are then not meaningful for every pair that can reach and leave that cycle; detecting a negative diagonal is not the same as propagating complete −∞-\infty affected-pair semantics.

Johnson: sparse all-pairs through reweighting #

Johnson’s algorithm supports APSP on a sparse directed graph with negative edges but no negative cycle:

  1. add a new super-source with zero-weight edges to every vertex;
  2. run Bellman–Ford to obtain a potential h(v)h(v) for each vertex and detect any negative cycle;
  3. reweight each edge as

w′(u,v)=w(u,v)+h(u)−h(v);w'(u,v)=w(u,v)+h(u)-h(v);

  1. run Dijkstra from each source using nonnegative w′w';
  2. convert distances back.

Potentials make reweighted edges nonnegative because Bellman–Ford distances satisfy

h(v)≤h(u)+w(u,v).h(v)\le h(u)+w(u,v).

For any ss-to-tt path, the potential terms telescope:

∑w′(u,v)=∑w(u,v)+h(s)−h(t).\sum w'(u,v)=\sum w(u,v)+h(s)-h(t).

Every ss-to-tt path receives the same endpoint-dependent offset, so their ordering is preserved. Johnson is a candidate for sparse APSP, not a universal performance winner; its actual cost depends on the repeated Dijkstra implementation and representation.

Reconstruct paths as certificates #

For one predecessor per vertex:

  1. reject the request if the target is unreachable or has no finite optimum;
  2. follow parent[target] backward until the source;
  3. guard against more than VV steps or repeated vertices;
  4. reverse the sequence;
  5. verify every recorded edge and sum its weights.

The sum must equal the reported distance within the declared numeric semantics. A cycle in a supposedly finite predecessor chain indicates stale updates, a negative-cycle condition, or corrupt state.

Shortest paths need not be unique. Equal relaxations may be ignored to return one deterministic path, or recorded as multiple predecessors to represent a shortest-path DAG. That is an output decision; the distance alone does not imply a unique tree.

Weight and numeric engineering #

The mathematical proof assumes exact ordered addition. Real implementations must define:

  • how a missing weight attribute is handled—error or explicit default;
  • how parallel edges are selected or preserved;
  • how absence differs from a zero-weight edge;
  • whether integer addition can overflow;
  • how floating-point rounding and NaN affect comparisons;
  • whether mutation during the run is forbidden.

Never let an infinity sentinel overflow when adding an edge. Never treat NaN as an ordinary weight: comparisons with it do not provide the total order the algorithms expect. With floating point, two mathematically equal path sums may differ by rounding order; exact equality and negative-cycle tolerances require a domain-specific policy rather than an arbitrary epsilon.

Shortest-path trees are not minimum spanning trees #

A shortest-path tree rooted at ss minimizes each root-to-vertex path. A minimum spanning tree minimizes the sum of selected tree-edge weights over the whole undirected graph. Those objectives differ.

Take triangle edges s–a(2), s–b(2), and a–b(1):

  • a shortest-path tree from s uses both weight-2 spokes, total tree weight 4, and reaches each target at distance 2;
  • an MST uses one spoke plus a–b(1), total tree weight 3, but its root-to-one-target route costs 3 instead of the graph’s direct distance 2.

The algorithms and cut properties for the second objective belong in Minimum Spanning Trees.

Failure diagnostics #

  1. Is the query single-pair, single-source, or all-pairs, and what output is required?
  2. Are direction, additive weight, zero, absence, and parallel-edge rules explicit?
  3. Are all weights equal, nonnegative, or allowed to be negative? Is the graph a DAG?
  4. Which invariant should make a label final: BFS layer, topological order, Dijkstra settlement, or pass count?
  5. Are finite labels backed by real predecessor paths with matching sums?
  6. Are stale priority-queue entries discarded?
  7. Is a negative cycle reachable from the source, and can it reach the target?
  8. Does complexity name the graph representation and priority queue?
  9. Could numeric overflow, rounding, NaN, or a bad infinity sentinel violate comparisons?
  10. Is someone optimizing total tree weight while asking for root-to-target distance, or vice versa?

Exercises #

  1. Run Dijkstra on the positive example through settlement of T. List every stale queue entry and explain why it is safe to skip.
  2. In the negative-edge counterexample, identify the exact step and inequality in the settling proof that fails.
  3. Add edge T→B(-5) to the Bellman–Ford example. Determine whether a negative cycle exists and which vertices have distance −∞-\infty from S under walk semantics.
  4. Give a graph with a negative cycle that is not reachable from source s. What should source-specific Bellman–Ford report under the scoped semantics described here?
  5. Prove the Floyd–Warshall recurrence by splitting optimal walks according to whether they use intermediate vertex kk.
  6. For the Johnson reweighting equation, show algebraically that two ss-to-tt paths preserve their weight ordering.
  7. A graph uses an adjacency matrix and array-based Dijkstra. Derive its O(V2)O(V^2) cost without mentioning EE.
  8. Construct two different shortest paths with the same total weight and explain how a one-parent implementation chooses between them.
Solutions
  1. The current extractions are S:0, B:1, A:3, C:4, T:7. Entries A:4, C:6, and T:10 become stale after later relaxations. Comparing the extracted key with current d[u] proves that a stale entry cannot represent the minimum current label and need not rescan outgoing edges.
  2. When A is settled at 2, the proof assumes every route whose first unsettled vertex is B cannot become cheaper on its remaining suffix. Edge B→A has weight -4, so the suffix from B back to settled A is negative: δ(S,B)=5\delta(S,B)=5 does not imply δ(S,A)≥5\delta(S,A)\ge5. The nonnegative-suffix inequality fails.
  3. Existing route S→B→C→T reaches T; adding T→B(-5) forms B→C→T→B with weight −4+2−5=−7-4+2-5=-7. It is reachable from S, so B, C, and T have distance −∞-\infty. In the stated Bellman–Ford example there is no edge from this cycle to A, so A keeps its finite distance 4.
  4. The unreachable cycle cannot affect any label backed by an s-rooted path. A source-specific algorithm should return finite/unreachable results for the source component and need not report the remote cycle unless its API promises whole-graph cycle detection.
  5. Assume no negative cycle affects the pair. An optimum with allowed intermediates {1,…,k} either never uses k, giving the first candidate, or uses it. Remove repeated nonnegative cycling as permitted; split at k into an i→k prefix and k→j suffix whose intermediates come from {1,…,k-1}. Their optimum sum gives the second candidate. Taking the minimum covers both exhaustive cases.
  6. For paths P1,P2P_1,P_2 from the same ss to the same tt, reweighting gives w′(Pi)=w(Pi)+h(s)−h(t)w'(P_i)=w(P_i)+h(s)-h(t). The same constant is added to both, so w(P1)≤w(P2)w(P_1)\le w(P_2) exactly when w′(P1)≤w′(P2)w'(P_1)\le w'(P_2).
  7. Repeat VV times: scan up to VV labels to choose the minimum unsettled vertex, then scan its full VV-cell matrix row to relax neighbors. Both nested costs are Θ(V2)\Theta(V^2); initialization is lower order.
  8. Example: s→a(1), s→b(1), a→t(1), b→t(1). Both paths cost 2. If relaxation updates only on strict improvement, whichever predecessor of t is processed first remains; stable neighbor/queue ordering can make that choice deterministic, but not mathematically unique.

Sources

  1. paperA note on two problems in connexion with graphs (Dijkstra, 1959)
  2. paperOn a Routing Problem (Bellman, 1958)
  3. paperAlgorithm 97: Shortest Path (Floyd, 1962)
  4. paperEfficient Algorithms for Shortest Paths in Sparse Networks (Johnson, 1977)
  5. bookAlgorithms, 4th Edition — 4.4 Shortest Paths
  6. docsNetworkX 3.6.1 — Dijkstra's Algorithm
  7. docsNetworkX 3.6.1 — Bellman–Ford predecessor and distance

Searches titles, aliases, headings, summaries, and full text.↑↓ move ↵ open esc close