Abstract

Given a graph with vertices (source ) and possibly negative edge weights, find the shortest distance from to every other vertex — or detect that no shortest path even exists, because a negative cycle is reachable.

  • Category: Dynamic Programming / Graph Shortest Path
  • Input: A graph with vertices, possibly negative edge weights, source
  • Output: Either "NEGATIVE CYCLE", or the shortest distance from to every vertex
  • Paradigm: Dynamic Programming, budgeting the number of edges allowed
  • Typical use cases: graphs with negative weights in general (not just DAGs); detecting negative cycles specifically (e.g. currency arbitrage detection, where a negative cycle means a risk-free profit loop exists)

Negative Cycles

Definition A negative cycle is a cycle in a graph such that the sum of its edge weights is negative.

From Dijkstra’s, one of its main constraints is that it only works with non-negative edge weights.

From the image, the cycle forms a negative cycle, since .

If a graph has negative edge weights and cycles, finding the shortest path can be problematic: with a negative cycle, there are paths whose lengths are unbounded from below — you can always go around the cycle one more time and get a “shorter” path, forever.


Problem Specification

  • Instance: Graph with vertices , possibly negative edge weights, source .
  • Solution Format: Either a negative-cycle report, or an array of shortest distances.
  • Constraints: None on the input weights (unlike Dijkstra’s).
  • Objective / Goal: Find the true shortest distance to every vertex, or correctly detect that no finite shortest distance exists for some vertex.

Candidate Strategies / Approaches

Dijkstra’s Algorithm ✘

If there are no negative cycles, Dijkstra’s can technically be adapted to find shortest paths — but its efficiency guarantee relies entirely on all edge weights being non-negative. With negative edge weights present (even without a negative cycle), Dijkstra’s runtime can blow up to exponential, since a vertex may need to be revisited and improved many times after being “finalized” too early.

Dynamic Programming (Bellman-Ford) ✔

Since DP always solves shortest paths on DAGs by processing vertices in a fixed (topological) order — see Shortest Path in a DAG — the natural generalization to graphs with cycles is to put a budget on how many edges we’re allowed to use. Budgeting the path length effectively “unrolls” the graph into layers indexed by , sidestepping the cycle problem entirely: you can never revisit an earlier, smaller budget layer.


Dynamic Programming Solution

1. Subproblems

Let be the length of the shortest path from to using at most edges.

2. Base Cases (assuming no negative cycles)

3. Recursion

To compute : ask which vertex is the second-to-last vertex on the shortest path from to using at most edges.

4. Ordering — What’s the Maximum Budget?

Answer: . Assuming no negative cycles, every shortest path must be a simple path (never repeats a vertex) — since repeating a vertex would mean a cycle exists on the path, and a non-negative cycle could only be removed to make the path shorter or equal, while a negative cycle would already violate the “no negative cycles” assumption. A simple path in a graph with vertices has at most edges. So order from .

Detecting Negative Cycles

What if we don’t know beforehand whether the graph has negative cycles? If there are no negative cycles, the array values will never improve after grows past (there’s no longer/better simple path to find). So:


Bellman-Ford Algorithm

Algorithm 16 Bellman Ford

procedure BFDP(G,v0G, v_0)

B[0,0]=0B[0,0] = 0

B[i,0]=B[i, 0] = \infty for all i0i \neq 0

for t=1,,nt = 1, \dots , n do

for i=0,,n1i = 0, \dots, n-1 do

B[i,t]=min(vj,vi)E[B[j,t1]+w(vj,vi)]B[i,t] = \underset{(v_j, v_i) \in E}{\min}[B[j, t-1] + w(v_j, v_i)]

for i=0,,n1i = 0, \dots, n-1 do

if B[i,n1]B[i,n]B[i, n-1] \neq B[i,n] then

return "Negative Cycle"

return [B[0,n],B[1,n],,B[n1,n]][B[0, n], B[1, n], \dots, B[n-1, n]]

Variables & Data Structures

NameTypePurpose
B2D array, B[i][t] = shortest distance from to using at most edges
tBudgetNumber of edges allowed so far, from up to (one extra round beyond , used purely to detect negative cycles)

Helper Functions / Operations Used

  • Min over incoming edges — for each , scan every edge ; per cell, summing to per full round of .

Proof of Correctness

Claim (assuming no negative cycle): equals the true shortest distance from to using at most edges.

  • Base case: (staying at the source uses 0 edges, correctly length 0), for (no vertex besides the source is reachable with 0 edges).
  • Inductive Hypothesis: is correct for every .
  • Inductive Step: consider the true shortest path to using at most edges. If , the trivial 0-edge path already achieves length 0, and no path can do better without a negative cycle, so remains correct. Otherwise (), that path — however many edges it actually uses, up to — arrives via some last edge , and the portion before that last edge is itself a shortest path to using at most edges (since removing the last edge removes exactly one edge from the budget). By the Inductive Hypothesis, that sub-path’s length is exactly . Since takes the minimum of over every possible predecessor , it correctly recovers the shortest such path.

Negative cycle detection is correct because, absent a negative cycle, every shortest path is simple (at most edges), so must stabilize by and never improve again — meaning any observed improvement between and can only be explained by a cycle that keeps helping, which (since it does help, i.e. strictly decreases the distance) must be a negative cycle.


Time & Space Complexity Analysis

General Case

For a graph with vertices and edges:

(the outer loop runs times for ; each round does work — for the vertices themselves, summed over all the incoming-edge scans).

Assuming (a connected graph, roughly):

ComplexityNotes
TimeSubstantially slower than Dijkstra’s Algorithm’s — the cost of tolerating negative weights
Space for the full B tableReducible to (two rows at a time) if negative-cycle detection isn’t needed and only final distances matter

Drawbacks / Constraints

  • Much slower than Dijkstra’s. Only use Bellman-Ford when negative edge weights are actually possible — if all weights are known non-negative, Dijkstra’s Algorithm is strictly better.
  • Detects that a negative cycle exists, but not automatically which vertices/edges form it. Recovering the actual cycle needs additional bookkeeping (e.g. tracing back predecessor pointers from a vertex whose distance kept improving past ).
  • Preconditions: the correctness proof above assumes no negative cycle for the “true shortest path” claim to even make sense — the algorithm’s real job when a negative cycle is present is just to detect that fact, not to report a (nonexistent) finite shortest distance.

References / Links