Skip to main content

Bellman Ford

This page provides introduction to Bellman Ford Algorithm.

Overview

Bellman ford is single source shortest path algorithm. Below is a table showing the types of graphs where Bellman Ford algorithm works.

Graph TypeDoes Bellman ford's Algorithm Works?
Directed with positive weight edgeYes
Directed with negative weight edgeYes(except when graph is negative weight cycle)
Undirected with positive weight edgeYes
Undirected with negative weight edgeYes(except when graph is negative weight cycle)

Here is example of graph with negative weight cycle.



bellmon-ford-1.svg

Run Bellman Ford

Let's apply the Bellman Ford algorithm to the directed graph shown below to calculate the distance of each node from the source node A\text{A}. The graph includes a negative weight edge, but no negative weight cycles.

bellmon-ford-2.svg

We begin by iterating through each edge V1\text{V} - 1 times, where V\text{V} represents the number of vertices in the graph. Distance of node A\text{A} from itself is 00.

Visiting edge AB\text{AB} gives us the distance of node B\text{B} from A\text{A} as 5050, which is less than the existing value of infinity. Therefore, we update the distance for B\text{B} in the distance hashmap.

bellmon-ford-3.svg

Visiting edge AC\text{AC} gives us the distance of node C\text{C} from A\text{A} as 4040, which is less than the existing value of infinity. Therefore, we update the distance for C\text{C} in the distance hashmap.

bellmon-ford-4.svg

Visiting edge AD\text{AD} gives us the distance of node D\text{D} from A\text{A} as 55, which is less than the existing value of infinity. Therefore, we update the distance for D\text{D} in the distance hashmap.

bellmon-ford-5.svg

Visiting edge BC\text{BC} gives us the distance of node C\text{C} from A\text{A} as 6060 (the distance of node B\text{B} from A\text{A} in the distance map plus the distance of edge BC\text{BC}). Since this is greater than the existing distance of node C\text{C} from A\text{A}, we don't update anything in the distance hashmap.

bellmon-ford-6.svg

Visiting edge BD\text{BD} gives us the distance of node D\text{D} from A\text{A} as 7070 (the distance of node D\text{D} from node B\text{B} in the distance map plus the distance of edge BD\text{BD}). Since this is greater than the existing distance of node D\text{D} from A\text{A}, we don't update anything in the distance hashmap.

bellmon-ford-7.svg

Visiting edge DE\text{DE} gives us the distance of node E\text{E} from A\text{A} as 99 (the distance of node D\text{D} from A\text{A} plus the distance of edge DE\text{DE}). Since this is less than the existing value of infinity, we update the distance of node E\text{E} from A\text{A} in the distance hashmap.

bellmon-ford-8.svg

Visiting edge EB\text{EB} gives us the distance of node B\text{B} from A\text{A} as 11-11 (the distance of node E\text{E} from node A\text{A} plus the distance of edge EB\text{EB}).

bellmon-ford-9.svg

This concludes the 1st1^{\text{st}} iteration of visiting all edges. Let's begin with the 2nd2^{\text{nd}} iteration.

Visiting edge AB\text{AB} gives us the distance of node B\text{B} from A\text{A} as 5050, which is greater than the existing distance of 11-11. Therefore, we don't update the distance in the hashmap.

bellmon-ford-10.svg

Visiting edge AC\text{AC} gives us the distance of node C\text{C} from A\text{A} as 4040, which is equal to the existing distance. Therefore, we don't update the distance in the hashmap.

bellmon-ford-11.svg

Visiting edge AD\text{AD} gives us the distance of node D\text{D} from A\text{A} as 55, which is equal to the existing distance. Therefore, we don't update the distance in the hashmap.

bellmon-ford-12.svg

Visiting edge BC\text{BC} gives us the distance of node C\text{C} from A\text{A} as 1-1 (distance of B\text{B} from node A\text{A} + distance of edge BC\text{BC}), which is less than the existing distance. Therefore, we update the distance of node C\text{C} in the hashmap.

bellmon-ford-13.svg

Visiting edge BD\text{BD} gives us the distance of node D\text{D} from A\text{A} as 88 (distance of B\text{B} from node A\text{A} + distance of edge BD\text{BD}), which is greater than the existing distance. Therefore, we don't update the distance in the hashmap.

bellmon-ford-14.svg

Visiting edge DE\text{DE} gives us the distance of node E\text{E} from A\text{A} as 99 (distance of D\text{D} from node A\text{A} + distance of edge DE\text{DE}), which is equal to the existing distance. Therefore, we don't update the distance in the hashmap.

bellmon-ford-15.svg

Visiting edge EB\text{EB} gives us the distance of node B\text{B} from A\text{A} as 11-11 (distance of E\text{E} from node A\text{A} + distance of edge EB\text{EB}), which is equal to the existing distance. Therefore, we don't update the distance in the hashmap.

bellmon-ford-16.svg

This concludes the 2nd2^{\text{nd}} iteration of visiting all edges. Continuing the 3rd3^{\text{rd}} and 4th4^{\text{th}} iterations yields similar results for the distance hashmap, as no further updates are made. At this point, the shortest distances from the source node A\text{A} to all other nodes have been finalized.

bellmon-ford-17.svg

Why V - 1 Iterations

Let's say we have the following graph, and we are finding the shortest path from node A\text{A} using the Bellman Ford algorithm.

bellmon-ford-18.svg

Now, if we apply the Bellman-Ford algorithm to the graph above, the first edge we iterate over will be BC\text{BC}. Since we don't yet know how to reach node B\text{B}, we can't update the distance hashmap.

bellmon-ford-19.svg

Now, we iterate over the edge AB\text{AB}. Since the distance of A\text{A} from itself is already known, we can update the distance of node B\text{B} from node A\text{A} to 1010.

bellmon-ford-20.svg

This concludes the 1st1^{\text{st}} iteration, but we still haven't determined the distance of node C\text{C} from node A\text{A}. This happened because when we first iterated over edge BC\text{BC}, we didn't know the distance of node B\text{B} from node A\text{A}.

This demonstrates that the algorithm's effectiveness also depends on the order in which we iterate over the edges. Iterating over the edges V1\text{V} - 1 times ensures that we have updated the shortest distances for all nodes, even if some connections were discovered in later iterations.

Therefore, in the Bellman Ford algorithm, we iterate over the edges V1\text{V} - 1 times to ensure that all shortest paths are correctly updated.

class Edge {
char src;
char dest;
int distance;

Edge(char src, char dest, int distance) {
this.src = src;
this.dest = dest;
this.distance = distance;
}
}

public HashMap<Character, Integer> bellmanFord(int vertices, Edge[] graph) {
HashMap<Character, Integer> dist = new HashMap<>();
for(int i = 0; i < vertices; i++) {
char ch = 'A' + i;
dist.put(ch, Integer.MAX_VALUE);
}
// source node
dist.put('A', 0);

for(int i = 0; i < vertices - 1; i++) {
for(Edge e: graph) {
if(dist.get(e.src) != Integer.MAX_VALUE && dist.get(e.src) + e.distance < dist.get(e.dest)) {
dist.put(e.dest, dist.get(e.src) + e.distance);
}
}
}

// run the algorithm one more time to check if graph has negative weight cycle
for(Edge e: graph) {
// distance reduces futher meaning graph as negative weight cycle
if(dist.get(e.src) != Integer.MAX_VALUE && dist.get(e.src) + e.distance < dist.get(e.dest)) {
throw new Excepttion("Graph contains negative weight cycle");
}
}
return dist;
}

Complexity

Let's say there are V\text{V} vertices and E\text{E} edges in a graph.

Time Complexity

Bellman ford algorithm runs for V1\text{V} - 1 times over all the edges, so time complexity is:

O(V E)\text{O(V E)}

Space Complexity

The algorithm uses space to store the distances of all vertices in a hashmap, therefore the total space complexity will be as below:

O(V)\text{O(V)}
info

Bellman Ford is useful for graphs with negative weights, but Dijkstra’s algorithm is typically preferred when all edge weights are non negative.