Bellman-Ford
The Bellman-Ford algorithm solves the single-source shortest-paths problem on a weighted, directed graph G=(V,E) in the general case in which edge weights may be negative. The algorithm returns a boolean value indicating whether there is a negative-weight cycle that is reachable from the source.
- If there is such a cycle, the algorithm indicates that no solution exists.
- If there is no such cycle, the algorithm produces the shortest paths and their weights.
It works with negative-weight cycles, but it is not reliable. If there is a negative cycle, d=-inf() but if we think of adding a constant to avoid negative cycles (ex: -8 is the most negative weight, I can add 8 to all edges), we will obtain dirty-values.
Data Structures
No relevant data structure to analyze, we can use either arrays or queues. This choice would not impact the outcome of the complexity.
Algorithm
It is composed of two parts:
- The first part is the main algorithm
- It performs n-1 brute force iterations, where it executes RELAX() on all edges of the graph. Basically, it consists of n-1 relaxations on all edges.
- Dijkstra only iterates through all edges once (m iterations).
- It performs n-1 brute force iterations, where it executes RELAX() on all edges of the graph. Basically, it consists of n-1 relaxations on all edges.
- The second part aims at locating the existence of negative cycles
BELLMAN_FORD(Graph G, Weight w, Vertex s)
INIT_SS(G, s)
for(i=1 to |G.V|-1):
for((u,v) in G.E):
RELAX(u,v, w(u,v));
for((u,v) in G.E):
if(d[v]>d[u]+w(u,v)):
return (False, d, Gπ);
return (True, d, Gπ); #No negative cyclesBELLMAN_FORD(Graph G, Weight w, Vertex s)
INIT_SS(G, s)
for(i=1 to |G.V|-1):
for((u,v) in G.E):
RELAX(u,v, w(u,v));
for((u,v) in G.E):
if(d[v]>d[u]+w(u,v)):
return (False, d, Gπ);
return (True, d, Gπ); #No negative cyclesFinal Time Complexity: T(n) = Θ(nm) = Θ(n + (n-1)m + m)
1 - Complexity Demonstration
- INIT_SS(): T(n) = Θ(n)
- First Part: T(n) = O(n-1 * m)
- For: T(n) = O(n-1)
- For each: T(n) = O(m)
- RELAX(): T(n) = O(1)
- For each: T(n) = O(m)
- For: T(n) = O(n-1)
- Second Part: T(n) = O(m)
- For each: T(n) = O(m)
- Check: T(n) = O(1)
- For each: T(n) = O(m)
BF vs Dijkstra

BF is more efficient when it comes to using data structures (maintaining a PQ is more expensive). Even though Dijkstra is a better fit almost always, we have can use BF more generally.
2 - Correctness Demonstration: BF's correctness theorem
Let's execute B.F. on a graph G=(V, E, w:E->R) with s∈V as source vertex.
- If G excludes negative cycles reachable from s, at the end of the algorithm the following statements stay true:
- d[u] = δ(s,u) ∀u∈V
- Gπ is a shortest-path tree
- The algorithm returns
True
- Else, the algorithm returns
False
The demonstration is divided into two parts. We distinguish the cases where:
- The graph excludes negative cycles
- The graph includes negative cycles
Part 1: Negative-Weight Cycles Excluded
Case 1: If we take a generic vertex u∈V, we have three cases
δ(s,u)=+inf(), by no path property- u cannot be reached by s.
δ(s,u)is a real number, so there must be at least one shortest-path p that is also simple,- In the SP set we can always find a path that is simple, which has max n-1 edges!
δ(s,u)=-inf()., by assumption
Case 2: Gπ is a shortest-path tree
- This is trivially true by a simple application of the convergence property
- The n-1 edges of the shortest path p
<x0 = s->x1->x2-> ... ->xq = u>go through BF as it follows:- d[s] = 0 = δ(s,s), by INIT_SS()
- RELAX(s, x1, w(s,x1)), since we are on a SP, d[x1] = δ(s,x1) [convergence]
- RELAX(s, x2, w(s,x2)), d[x2] = δ(s,x2) [convergence]
- Repeat until it reaches the last vertex. When it comes to q, we only need n-1 iterations because we are on SP. RELAX(s, u, w(s,u)) -> d[u]=δ(s,u)
Case 3: The algorithm returns True when there are no negative cycles. It means, that if d[v] <= d[u]+w(u,v) for all edges (u,v) in E, the algorithm returns True by construction of BF
δ(s,v) <= δ(s,u)+w(u,v), by triangular propertyd[v] = δ(s,v)for each v in V, by construction of BFd[v]<= d[u]+w(u,v), Trivially
Part 2: Negative-Weight Cycles Included
If in G there are negative cycles reachable from s, at the end of the algorithm the following statement stays true: The algorithm returns False.
Ad absurdum, we suppose there exists a negative-weighted cycle reachable from s, and that at the end of the algorithm the following statement stays true: The algorithm returns True.
- Returning TRUE means that when
d[v] <= d[u]+w(u,v), for all edges by hypothesis - Let's call
c = <x0, x1, ..., xq>, with x0 = xqthe negative cycle reachable from s.- This means sum(w(xi-1, xi), i=1 to q) < 0 so
w(c)<0
- This means sum(w(xi-1, xi), i=1 to q) < 0 so
- If the point 1 stands true for all edges, we can say that for all i=1 to q,
d[xi]<=d[xi-1]+w(xi-1, xi)- By summing everything we would obtain:
sum(d[xi], i=1 to q) <= sum(d[xi-1], i=1 to q) + sum(w(xi-1, xi), i=1 to q) - However, we find out that
sum(d[xi], i=1 to q) = sum(d[xi-1], i=1 to q)since,d[x1]+d[x2]+d[x3]+ ... +d[xq-1]+d[xq] <= d[x0]+d[x1]+d[x2]+d[x3]+ ... + d[xq-1]- By taking out the common members we have, d[xq] <= d[x0]
- We know xq=x0 since this is a cycle!
- By summing everything we would obtain:
- What is left from 3.1 is sum(w(xi-1, xi), i=1 to q)>= 0 so
w(c)>=0, which is absurd!d[xq]<=d[x0]+sum(w(xi-1, xi), i=1 to q)
Example
CPU Improvement
Conclusions
Best to be used when there are no negative cycles, but can be used with negative weights!