Detect a negative cycle in a Graph using Shortest Path Faster Algorithm
Last Updated :
10 Aug, 2021
Given a graph G consisting of nodes valued [0, N – 1], a source S, and an array Edges[][3] of type {u, v, w} that denotes that there is a directed edge between node u and v with weight w, the task is to check if there exists a negative cycle from the given source. If found to be true, then print “Yes”. Otherwise, print “No”.
A negative cycle is a cycle in which the sum of all its weight in that cycle is negative.
Examples:
Input: N = 4, M = 4, Edges[][] = {{0, 1, 1}, {1, 2, -1}, {2, 3, -1}, {3, 0, -1}}, S = 0
Output: Yes
Explanation:
Starting from the source node 0, the graph contains cycle as 0 -> 1 -> 2 -> 3 -> 0.
The sum of weight in the above path is 1 – 1 – 1 – 1 = -2.
Therefore, the graph contains a negative cycle.
Input: N = 4, M = 5, Edges[][] = {{0, 2, -2}, {1, 0, 4}, {1, 2, -3}, {2, 3}, {3, 1}}, W[] = {-2, 4, -3, 2, -1}, S = 1
Output: Yes
Explanation:
Starting from the source node 1, the graph contains cycle as 1 -> 2 -> 3 -> 1.
The sum of weight in the above path is -3 + 2 – 1 = -2.
Therefore, the graph contains a negative cycle.
Approach: The idea is to use the Shortest Path Faster Algorithm(SPFA) to find if a negative cycle is present and reachable from the source vertex in a graph. Follow the below steps to solve the problem:
- Initialize the arrays dis[] with large value, vis[] with false and cnt[] to store the count about how many times a vertex has been relaxed.
- Traverse the graph using the SPFA algorithm.
- Increment the count for each vertex whenever the vertex is relaxed.
The term relaxation means updating the cost of all vertices connected to a vertex v if those costs would be improved by including the path via vertex v.
- Stop the algorithm and print “Yes” as soon as some vertex got relaxed for the Nth time as there are only N vertices i.e., from 0 to N – 1.
- Otherwise, print “No”.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
bool sfpa( int V, int src, int Edges[][3],
int M)
{
vector<pair< int , int > > g[V];
for ( int i = 0; i < M; i++) {
int u = Edges[i][0];
int v = Edges[i][1];
int w = Edges[i][2];
g[u].push_back({ v, w });
}
vector< int > dist(V, INT_MAX);
vector< bool > inQueue(V, false );
vector< int > cnt(V, 0);
dist[src] = 0;
queue< int > q;
q.push(src);
inQueue[src] = true ;
while (!q.empty()) {
int u = q.front();
q.pop();
inQueue[u] = false ;
for (pair< int , int > x : g[u]) {
int v = x.first;
int cost = x.second;
if (dist[v] > dist[u] + cost) {
dist[v] = dist[u] + cost;
if (!inQueue[v]) {
q.push(v);
inQueue[v] = true ;
cnt[v]++;
if (cnt[v] >= V)
return true ;
}
}
}
}
return false ;
}
int main()
{
int N = 4;
int src = 0;
int M = 4;
int Edges[][3] = { { 0, 1, 1 },
{ 1, 2, -1 },
{ 2, 3, -1 },
{ 3, 0, -1 } };
if (sfpa(N, src, Edges, M) == true )
cout << "Yes" << endl;
else
cout << "No" << endl;
return 0;
}
|
Java
import java.util.*;
class GFG{
static class pair
{
int first, second;
public pair( int first,
int second)
{
this .first = first;
this .second = second;
}
}
static boolean sfpa( int V, int src,
int Edges[][], int M)
{
Vector<pair> []g = new Vector[V];
for ( int i = 0 ; i < V; i++)
{
g[i] = new Vector<pair>();
}
for ( int i = 0 ; i < M; i++)
{
int u = Edges[i][ 0 ];
int v = Edges[i][ 1 ];
int w = Edges[i][ 2 ];
g[u].add( new pair(v, w));
}
int []dist = new int [V];
Arrays.fill(dist, Integer.MAX_VALUE);
boolean []inQueue = new boolean [V];
int []cnt = new int [V];
dist[src] = 0 ;
Queue<Integer> q = new LinkedList<>();
q.add(src);
inQueue[src] = true ;
while (!q.isEmpty())
{
int u = q.peek();
q.remove();
inQueue[u] = false ;
for (pair x : g[u])
{
int v = x.first;
int cost = x.second;
if (dist[v] > dist[u] + cost)
{
dist[v] = dist[u] + cost;
if (!inQueue[v])
{
q.add(v);
inQueue[v] = true ;
cnt[v]++;
if (cnt[v] >= V)
return true ;
}
}
}
}
return false ;
}
public static void main(String[] args)
{
int N = 4 ;
int src = 0 ;
int M = 4 ;
int Edges[][] = {{ 0 , 1 , 1 },
{ 1 , 2 , - 1 },
{ 2 , 3 , - 1 },
{ 3 , 0 , - 1 }};
if (sfpa(N, src, Edges, M) == true )
System.out.print( "Yes" + "\n" );
else
System.out.print( "No" + "\n" );
}
}
|
Python3
import sys
def sfpa(V, src, Edges, M):
g = [[] for i in range (V)]
for i in range (M):
u = Edges[i][ 0 ]
v = Edges[i][ 1 ]
w = Edges[i][ 2 ]
g[u].append([v, w])
dist = [sys.maxsize for i in range (V)]
inQueue = [ False for i in range (V)]
cnt = [ 0 for i in range (V)]
dist[src] = 0
q = []
q.append(src)
inQueue[src] = True
while ( len (q)):
u = q[ 0 ]
q.remove(q[ 0 ])
inQueue[u] = False
for x in g[u]:
v = x[ 0 ]
cost = x[ 1 ]
if (dist[v] > dist[u] + cost):
dist[v] = dist[u] + cost
if (inQueue[v] = = False ):
q.append(v)
inQueue[v] = True
cnt[v] + = 1
if (cnt[v] > = V):
return True
return False
if __name__ = = '__main__' :
N = 4
src = 0
M = 4
Edges = [ [ 0 , 1 , 1 ],
[ 1 , 2 , - 1 ],
[ 2 , 3 , - 1 ],
[ 3 , 0 , - 1 ] ]
if (sfpa(N, src, Edges, M) = = True ):
print ( "Yes" )
else :
print ( "No" )
|
C#
using System;
using System.Collections.Generic;
class GFG{
class pair
{
public int first, second;
public pair( int first,
int second)
{
this .first = first;
this .second = second;
}
}
static bool sfpa( int V, int src,
int [,]Edges, int M)
{
List<pair> []g = new List<pair>[V];
for ( int i = 0; i < V; i++)
{
g[i] = new List<pair>();
}
for ( int i = 0; i < M; i++)
{
int u = Edges[i, 0];
int v = Edges[i, 1];
int w = Edges[i, 2];
g[u].Add( new pair(v, w));
}
int []dist = new int [V];
for ( int i = 0; i < V; i++)
dist[i] = int .MaxValue;
bool []inQueue = new bool [V];
int []cnt = new int [V];
dist[src] = 0;
Queue< int > q = new Queue< int >();
q.Enqueue(src);
inQueue[src] = true ;
while (q.Count != 0)
{
int u = q.Peek();
q.Dequeue();
inQueue[u] = false ;
foreach (pair x in g[u])
{
int v = x.first;
int cost = x.second;
if (dist[v] > dist[u] + cost)
{
dist[v] = dist[u] + cost;
if (!inQueue[v])
{
q.Enqueue(v);
inQueue[v] = true ;
cnt[v]++;
if (cnt[v] >= V)
return true ;
}
}
}
}
return false ;
}
public static void Main(String[] args)
{
int N = 4;
int src = 0;
int M = 4;
int [,]Edges = {{0, 1, 1},
{1, 2, -1},
{2, 3, -1},
{3, 0, -1}};
if (sfpa(N, src, Edges, M) == true )
Console.Write( "Yes" + "\n" );
else
Console.Write( "No" + "\n" );
}
}
|
Javascript
<script>
class pair
{
constructor(first, second)
{
this .first = first;
this .second = second;
}
}
function sfpa(V, src, Edges, M)
{
var g = Array.from(Array(V), ()=>Array());
for ( var i = 0; i < M; i++)
{
var u = Edges[i][0];
var v = Edges[i][1];
var w = Edges[i][2];
g[u].push( new pair(v, w));
}
var dist = Array(V);
for ( var i = 0; i < V; i++)
dist[i] = 1000000000;
var inQueue = Array(V).fill( false );
var cnt = Array(V).fill(0);
dist[src] = 0;
var q = [];
q.push(src);
inQueue[src] = true ;
while (q.length != 0)
{
var u = q[0];
q.shift();
inQueue[u] = false ;
for ( var x of g[u])
{
var v = x.first;
var cost = x.second;
if (dist[v] > dist[u] + cost)
{
dist[v] = dist[u] + cost;
if (!inQueue[v])
{
q.push(v);
inQueue[v] = true ;
cnt[v]++;
if (cnt[v] >= V)
return true ;
}
}
}
}
return false ;
}
var N = 4;
var src = 0;
var M = 4;
var Edges = [[0, 1, 1],
[1, 2, -1],
[2, 3, -1],
[3, 0, -1]];
if (sfpa(N, src, Edges, M) == true )
document.write( "Yes" + "<br>" );
else
document.write( "No" + "<br>" );
</script>
|
Time Complexity: O(N*M), where N is the number of vertices and M is the number of edges.
Auxiliary Space: O(N + M)
Share your thoughts in the comments
Please Login to comment...