Bellman-Ford and Negative Cycles
Bellman-Ford finds shortest paths even with negative edge weights, and as a side effect it detects negative cycles, which is exactly how currency arbitrage gets found algorithmically.
Prerequisites: Dijkstra's Shortest Paths, Graph Representations
Dijkstra's algorithm finalises each node's distance the moment it's popped from the queue, and that shortcut breaks the instant an edge has negative weight, a later, cheaper path through a negative edge can undercut a distance that was already declared final. Bellman-Ford gives up that shortcut and, in exchange, handles negative edges correctly, plus it can tell you when the whole question "what's the shortest path" stops making sense.
The idea: relax every edge, V-1 times, no shortcuts
Bellman-Ford does the same relaxation Dijkstra does,
, but instead of picking edges cleverly via a priority queue, it just relaxes every edge in the graph, in any order, and repeats the whole pass times. The claim is: after passes, every shortest path using at most edges has been found. Since a shortest simple path visits each node at most once, it uses at most edges, so passes are guaranteed enough, no priority queue, no greedy assumption, so negative weights are fine. Cost is , worse than Dijkstra's , which is the price of dropping the non-negativity requirement.
The bonus: run one more pass, pass . If any distance still improves, some cycle in the graph has negative total weight, a loop you could traverse forever to make the "shortest path" arbitrarily negative, so no finite answer exists. That -th pass is a negative-cycle detector.
Worked example: currency arbitrage
Suppose $1 buys 0.90 EUR, 1 EUR buys 0.80 GBP, and 1 GBP buys 1.45 USD. Multiply the three rates: . Round-tripping $1 through EUR and GBP returns $1.044, free money, an arbitrage. Bellman-Ford finds this automatically by weighting each edge : since turns products into sums, a profitable loop (product ) becomes a cycle whose weights sum to a negative number, and the -th relaxation pass will keep finding improvements on it forever, flagging exactly that cycle.
def bellman_ford(edges, n, src): # edges: list of (u, v, w); O(VE)
dist = [float("inf")] * n
dist[src] = 0
for _ in range(n - 1):
for u, v, w in edges:
if dist[u] + w < dist[v]:
dist[v] = dist[u] + w
for u, v, w in edges: # V-th pass: negative-cycle check
if dist[u] + w < dist[v]:
return None # negative cycle reachable from src
return dist
Bellman-Ford relaxes every edge times instead of using a priority queue, slower than Dijkstra but correct with negative weights, and its extra pass detects negative cycles. Weighting FX edges as turns arbitrage-hunting into negative-cycle detection.
A negative cycle means "no shortest path exists," not "the shortest path is very negative." If your traversal can loop through it, the true minimum is , and Bellman-Ford's job on such a graph is only to report that the cycle exists, not to output a distance.
Where it shows up
Interview framing: "cheapest flights within k stops" bounds the number of relaxation passes to , which is Bellman-Ford with an early stop. On a desk, triangular and multi-leg FX arbitrage detection is the canonical application; the same negative-cycle idea generalises to any market where implied round-trip pricing (funding rates, cross-listed securities, calendar spreads) should multiply to 1 but occasionally doesn't.
Discussion
💡 Discussion rules
- Ask and answer about this concept. Off-topic gets removed.
- No homework dumps. Show what you tried first.
- Corrections are welcome. Cite a source when you claim an error.
Loading discussion…
Related concepts
Practice in interviews
Further reading
- Cormen, Leiserson, Rivest & Stein, Introduction to Algorithms (ch. 24)
- Bellman, On a Routing Problem (1958)