Given a weighted graph with V vertices and E edges, along with a source vertexsrc, the task is to compute the shortest distances from the source to all other vertices. If a vertex is unreachable from the source, its distance should be marked as 108. In the presence of a negative weight cycle, return -1 to signify that shortest path calculations are not feasible.
Output: [0, 5, 6, 6, 7] Explanation: Shortest Paths: For 0 to 1 minimum distance will be 5. By following path 0 → 1 For 0 to 2 minimum distance will be 6. By following path 0 → 1 → 2 For 0 to 3 minimum distance will be 6. By following path 0 → 1 → 2 → 4 → 3 For 0 to 4 minimum distance will be 7. By following path 0 → 1 → 2 → 4
Output: [-1] Explanation: The graph contains a negative weight cycle formed by the path 1 → 2 → 3 → 1, where the total weight of the cycle is negative.
Approach: Bellman-Ford Algorithm - O(V*E) Time and O(V) Space
Negative weight cycle:
A negative weight cycle is a cycle in a graph, whose sum of edge weights is negative. If you traverse the cycle, the total weight accumulated would be less than zero.
In the presence of negative weight cycle in the graph, the shortest path doesn't exist because with each traversal of the cycle shortest path keeps decreasing.
Limitation of Dijkstra's Algorithm:
Since, we need to find the single source shortest path, we might initially think of using Dijkstra's algorithm. However, Dijkstra is not suitable when the graph consists of negative edges. The reason is, it doesn't revisit those nodes which have already been marked as visited. If a shorter path exists through a longer route with negative edges, Dijkstra's algorithm will fail to handle it.
Principle of Relaxation of Edges
Relaxation means updating the shortest distance to a node if a shorter path is found through another node. For an edge (u, v) with weight w:
If going through u gives a shorter path to v from the source node (i.e., distance[v] > distance[u] + w), we update the distance[v] as distance[u] + w.
In the bellman-ford algorithm, this process is repeated (V - 1) times for all the edges.
Why Relaxing Edges (V - 1) times gives us Single Source Shortest Path?
A shortest path between two vertices can have at most (V - 1) edges. It is not possible to have a simple path with more than (V - 1) edges (otherwise it would form a cycle). Therefore, repeating the relaxation process (V - 1) times ensures that all possible paths between source and any other node have been covered.
Assuming node 0 as the source vertex, let's see how we can relax the edges to find the shortest paths:
In the first relaxation, since the shortest paths for vertices 1 and 2 are unknown (infinite, i.e., 108), the shortest paths for vertices 2 and 3 will also remain infinite (108). And, for vertex 1, the distance will be updated to 4, as dist[0] + 4 < dist[1] (i.e., 0 + 4 < 108).
In the second relaxation, the shortest path for vertex 2 is still infinite (e.g. 108), which means the shortest path for vertex 3 will also remain infinite. For vertex 2, the distance can be updated to 3, as dist[1] + (-1) = 3.
In the third relaxation, the shortest path for vertex 3 will be updated to 5, as dist[2] + 2 = 5.
So, in above example, dist[1] is updated in 1st relaxation, dist[2] is updated in second relaxation, so the dist for the last node (V - 1), will be updated in (V - 1) th relaxation.
Detection of a Negative Weight Cycle
As we have discussed earlier that, we need (V - 1) relaxations of all the edges to achieve single source shortest path. If one additional relaxation (Vth) for any edge is possible, it indicates that some edges with overall negative weight has been traversed once more. This indicates the presence of a negative weight cycle in the graph.
Bellman-Ford is a single source shortest path algorithm. It effectively works in the cases of negative edges and is able to detect negative cycles as well. It works on the principle of relaxation of the edges.
Illustration:
1 / 6
C++
#include<iostream>#include<vector>usingnamespacestd;vector<int>bellmanFord(intV,vector<vector<int>>&edges,intsrc){// Initially distance from source to all // other vertices is not known(Infinite).vector<int>dist(V,1e8);dist[src]=0;// Relaxation of all the edges V times, not (V - 1) as we// need one additional relaxation to detect negative cyclefor(inti=0;i<V;i++){for(vector<int>edge:edges){intu=edge[0];intv=edge[1];intwt=edge[2];if(dist[u]!=1e8&&dist[u]+wt<dist[v]){// If this is the Vth relaxation, then there is// a negative cycleif(i==V-1)return{-1};// Update shortest distance to node vdist[v]=dist[u]+wt;}}}returndist;}intmain(){// Number of vertices in the graphintV=5;// Edge list representation: {source, destination, weight}vector<vector<int>>edges={{1,3,2},{4,3,-1},{2,4,1},{1,2,1},{0,1,5}};// Define the source vertexintsrc=0;// Run Bellman-Ford algorithm to get shortest paths from srcvector<int>ans=bellmanFord(V,edges,src);// Output the shortest distances from src to all verticesfor(intdist:ans)cout<<dist<<" ";return0;}
// Relaxation of all the edges V times, not (V - 1) as we
// need one additional relaxation to detect negative cycle
for (inti=0; i<V; i++) {
for (vector<int>edge : edges) {
intu=edge[0];
intv=edge[1];
intwt=edge[2];
if (dist[u] !=1e8&&dist[u] +wt<dist[v]) {
// If this is the Vth relaxation, then there is
// a negative cycle
if(i==V-1)
return {-1};
// Update shortest distance to node v
dist[v] =dist[u] +wt;
}
}
}
returndist;
}
intmain() {
// Number of vertices in the graph
intV=5;
// Edge list representation: {source, destination, weight}
vector<vector<int>>edges= {
{1, 3, 2},
{4, 3, -1},
{2, 4, 1},
{1, 2, 1},
{0, 1, 5}
};
// Define the source vertex
intsrc=0;
// Run Bellman-Ford algorithm to get shortest paths from src
vector<int>ans=bellmanFord(V, edges, src);
// Output the shortest distances from src to all vertices
for (intdist : ans)
cout<<dist<<" ";
return0;
}
Java
importjava.util.Arrays;classGfG{staticint[]bellmanFord(intV,int[][]edges,intsrc){// Initially distance from source to all other vertices // is not known(Infinite).int[]dist=newint[V];Arrays.fill(dist,(int)1e8);dist[src]=0;// Relaxation of all the edges V times, not (V - 1) as we // need one additional relaxation to detect negative cyclefor(inti=0;i<V;i++){for(int[]edge:edges){intu=edge[0];intv=edge[1];intwt=edge[2];if(dist[u]!=1e8&&dist[u]+wt<dist[v]){// If this is the Vth relaxation, then there is// a negative cycleif(i==V-1)returnnewint[]{-1};// Update shortest distance to node vdist[v]=dist[u]+wt;}}}returndist;}publicstaticvoidmain(String[]args){// Number of vertices in the graphintV=5;// Edge list representation: {source, destination, weight}int[][]edges=newint[][]{{1,3,2},{4,3,-1},{2,4,1},{1,2,1},{0,1,5}};// Source vertex for Bellman-Ford algorithmintsrc=0;// Run Bellman-Ford algorithm from the source vertexint[]ans=bellmanFord(V,edges,src);// Print shortest distances from the source to all verticesfor(intdist:ans)System.out.print(dist+" ");}}
Python
defbellmanFord(V,edges,src):# Initially distance from source to all other vertices # is not known(Infinite) e.g. 1e8.dist=[100000000]*Vdist[src]=0# Relaxation of all the edges V times, not (V - 1) as we# need one additional relaxation to detect negative cycleforiinrange(V):foredgeinedges:u,v,wt=edgeifdist[u]!=100000000anddist[u]+wt<dist[v]:# If this is the Vth relaxation, then there # is a negative cycleifi==V-1:return[-1]# Update shortest distance to node vdist[v]=dist[u]+wtreturndistif__name__=='__main__':V=5edges=[[1,3,2],[4,3,-1],[2,4,1],[1,2,1],[0,1,5]]src=0ans=bellmanFord(V,edges,src)print(' '.join(map(str,ans)))
C#
usingSystem;classGfG{// Function to perform the Bellman-Ford algorithmstaticint[]bellmanFord(intV,int[,]edges,intsrc){// Initialize distances from source to all// vertices as "infinity" (represented by 1e8)int[]dist=newint[V];for(inti=0;i<V;i++)dist[i]=(int)1e8;// Distance to the source is always 0dist[src]=0;// Get the number of edges from the 2D edge arrayintE=edges.GetLength(0);// Relax all edges V times// The extra iteration (V-th) is used to detect a // negative weight cyclefor(inti=0;i<V;i++){for(intj=0;j<E;j++){// Extract edge info: from u to v with weight wtintu=edges[j,0];intv=edges[j,1];intwt=edges[j,2];// Only proceed if u has already been reached // (i.e., not infinity)if(dist[u]!=(int)1e8&&dist[u]+wt<dist[v]){// If this is the V-th iteration and relaxation is still// possible, it means there is a negative weight cycleif(i==V-1)// Indicate presence of negative cyclereturnnewint[]{-1};// Update the distance to vertex v through vertex udist[v]=dist[u]+wt;}}}// Return the final shortest distancesreturndist;}staticvoidMain(){// Number of vertices in the graphintV=5;// Edge list: each row represents {source, destination, weight}int[,]edges={{1,3,2},{4,3,-1},{2,4,1},{1,2,1},{0,1,5}};// Source vertexintsrc=0;// Call Bellman-Ford and store the resultint[]ans=bellmanFord(V,edges,src);// Print the shortest distances from source to all verticesforeach(intdinans)Console.Write(d+" ");}}
JavaScript
functionbellmanFord(V,edges,src){// Initially distance from source to all // other vertices is not known(Infinite).letdist=newArray(V).fill(1e8);dist[src]=0;// Relaxation of all the edges V times, not (V - 1) as we// need one additional relaxation to detect negative cyclefor(leti=0;i<V;i++){for(letedgeofedges){letu=edge[0];letv=edge[1];letwt=edge[2];if(dist[u]!==1e8&&dist[u]+wt<dist[v]){// If this is the Vth relaxation, then there is// a negative cycleif(i===V-1)return[-1];// Update shortest distance to node vdist[v]=dist[u]+wt;}}}returndist;}// Driver Code letV=5;letedges=[[1,3,2],[4,3,-1],[2,4,1],[1,2,1],[0,1,5]];letsrc=0;letans=bellmanFord(V,edges,src);console.log(ans.join(" "));
We use cookies to ensure you have the best browsing experience on our website. By using our site, you
acknowledge that you have read and understood our
Cookie Policy &
Privacy Policy
Improvement
Suggest Changes
Help us improve. Share your suggestions to enhance the article. Contribute your expertise and make a difference in the GeeksforGeeks portal.
Create Improvement
Enhance the article with your expertise. Contribute to the GeeksforGeeks community and help create better learning resources for all.