The Bellman-Ford algorithm computes shortest paths from a single source vertex to every other vertex in a weighted Graph, allowing negative edge weights. It also detects negative-weight cycles — situations where shortest paths don’t exist because you can keep going around the loop and shrink the total weight forever.
It’s the natural counterpart to Dijkstra: slower ( vs. ), but it works on graphs Dijkstra can’t handle.
The idea
Dijkstra grows a cloud of finalised vertices and never revisits one. That works only when distances increase monotonically as you grow the cloud — true for non-negative weights, but breaks down with negatives.
Bellman-Ford takes a different approach: keep relaxing every edge, over and over. After rounds of relaxing all edges, the distance estimate is correct for every vertex reachable from the source by a path of at most edges. Since any shortest path uses at most edges (more than that means a cycle, which can’t help if there are no negative cycles), rounds are enough.
Algorithm
- Initialise and for every other vertex.
- Repeat times: for every edge with weight , relax:
- After the rounds, do one more pass over every edge. If any relaxation still improves a distance, the graph contains a negative-weight cycle reachable from the source — report it. Otherwise the distances are final.
The relaxation step is identical to Dijkstra’s. The difference is that Bellman-Ford relaxes every edge in every round, instead of carefully picking which vertex to expand.
Why rounds
Claim: after round , is the weight of the shortest path from the source to that uses at most edges.
Proof by induction. Base case : only the source has finite distance, which is correct. Inductive step: at the start of round , every vertex has the right distance for paths of length at most . The relaxations in round extend each of those paths by one more edge — so by the end of round , every vertex has the right distance for paths of length at most .
A simple shortest path has at most edges (it can’t visit the same vertex twice without forming a cycle). So rounds suffice.
Detecting negative cycles
After rounds, the distances are final — unless there’s a negative cycle reachable from the source. A negative cycle means you can always find a shorter path by going around it once more. So one more relaxation pass: if anything improves, a reachable negative cycle exists.
The cycle can also be reconstructed using predecessor pointers: start from a vertex whose distance just improved, walk backward through pred for steps (guaranteed to land inside the cycle), then walk one more loop to extract it.
Implementation
#define V 5 // number of vertices
#define E 8 // number of edges
typedef struct { int src, dst, weight; } Edge;
bool BellmanFord(Edge edges[E], int source, int dist[V]) {
for (int i = 0; i < V; i++) dist[i] = INT_MAX;
dist[source] = 0;
// V-1 relaxation rounds
for (int i = 0; i < V - 1; i++) {
for (int j = 0; j < E; j++) {
int u = edges[j].src, v = edges[j].dst, w = edges[j].weight;
if (dist[u] != INT_MAX && dist[u] + w < dist[v]) {
dist[v] = dist[u] + w;
}
}
}
// One more pass to detect a negative cycle
for (int j = 0; j < E; j++) {
int u = edges[j].src, v = edges[j].dst, w = edges[j].weight;
if (dist[u] != INT_MAX && dist[u] + w < dist[v]) {
return false; // negative cycle reachable
}
}
return true;
}The structure is intentionally dumb: just relax every edge over and over. No priority queue, no sorting, no bookkeeping beyond the distance array.
Big O
- Time: — rounds, relaxations each.
- Space: for the distance array (and the predecessor array if you want to reconstruct paths).
For a sparse graph () this is — same as the naïve array-based Dijkstra. For a dense graph () it’s , much slower than Dijkstra’s on the same graph (the simple array-PQ Dijkstra, which beats the heap version when the graph is dense). On dense graphs the heap version of Dijkstra is not the right comparison; the array-PQ version is. The cost of generality.
When to use which
Use Dijkstra when all edge weights are non-negative. It’s faster.
Use Bellman-Ford when:
- Some edge weights are negative.
- You need to detect negative cycles (e.g., currency arbitrage detection — a negative cycle in space means a profitable round trip).
- You’re implementing a distance-vector routing protocol (RIP uses a distributed Bellman-Ford).
For all-pairs shortest paths with negative weights, see the Floyd-Warshall algorithm — same family of dynamic-programming relaxation, but for the full all-pairs answer.