Given a directed graph with V vertices numbered from 0 to V - 1 and E directed edges. The graph is represented using a 2D array edges[][] of size E, where each entry edges[i] = [u, v] denotes a directed edge from vertex u to vertex v.
Check whether the graph contains any cycle. Return true if there exists at least one cycle in the graph; otherwise, return false.
To detect a cycle in a directed graph, we use Depth First Search (DFS). If DFS reaches a vertex that is already present in the current DFS path, a cycle exists.
Using only visited[] is not enough. A vertex may have been visited during an earlier DFS traversal but may not be part of the current DFS path. Therefore, we also keep track of the vertices currently being explored.
For this, we use two arrays:
visited[]: Marks vertices that have been visited at least once.
recStack[]: Marks vertices that are currently present in the DFS recursion path.
If during DFS we reach a vertex whose recStack[] value is true, a cycle is found. After completely exploring all adjacent vertices of a node, we remove it from the current DFS path by setting recStack[u] = false. This ensures that recStack[] contains only the vertices that belong to the current DFS path.
C++
#include<bits/stdc++.h>usingnamespacestd;booldfs(vector<vector<int>>&adj,intu,vector<bool>&visited,vector<bool>&recStack){// Node is already in the current DFS pathif(recStack[u])returntrue;// Node is already visitedif(visited[u])returnfalse;visited[u]=true;recStack[u]=true;// Visit all adjacent nodesfor(intv:adj[u]){if(dfs(adj,v,visited,recStack))returntrue;}// Remove node from current DFS pathrecStack[u]=false;returnfalse;}boolisCyclic(intV,vector<vector<int>>&edges){vector<vector<int>>adj(V);// Create adjacency listfor(auto&edge:edges){adj[edge[0]].push_back(edge[1]);}vector<bool>visited(V,false);vector<bool>recStack(V,false);// Check all componentsfor(inti=0;i<V;i++){if(!visited[i]&&dfs(adj,i,visited,recStack))returntrue;}returnfalse;}intmain(){intV=4;vector<vector<int>>edges={{0,1},{1,2},{2,0},{2,3}};cout<<(isCyclic(V,edges)?"true":"false")<<endl;return0;}
Java
importjava.util.ArrayList;classGFG{publicstaticbooleandfs(ArrayList<ArrayList<Integer>>adj,intu,boolean[]visited,boolean[]recStack){// Node is already in the current DFS pathif(recStack[u])returntrue;// Node is already visitedif(visited[u])returnfalse;visited[u]=true;recStack[u]=true;// Visit all adjacent nodesfor(intv:adj.get(u)){if(dfs(adj,v,visited,recStack))returntrue;}// Remove node from current DFS pathrecStack[u]=false;returnfalse;}publicstaticbooleanisCyclic(intV,int[][]edges){ArrayList<ArrayList<Integer>>adj=newArrayList<>();for(inti=0;i<V;i++)adj.add(newArrayList<>());// Create adjacency listfor(int[]edge:edges){adj.get(edge[0]).add(edge[1]);}boolean[]visited=newboolean[V];boolean[]recStack=newboolean[V];// Check all componentsfor(inti=0;i<V;i++){if(!visited[i]&&dfs(adj,i,visited,recStack))returntrue;}returnfalse;}publicstaticvoidmain(String[]args){intV=4;int[][]edges={{0,1},{1,2},{2,0},{2,3}};System.out.println(isCyclic(V,edges)?"true":"false");}}
Python
defdfs(adj,u,visited,recStack):# Node is already in the current DFS pathifrecStack[u]:returnTrue# Node is already visitedifvisited[u]:returnFalsevisited[u]=TruerecStack[u]=True# Visit all adjacent nodesforvinadj[u]:ifdfs(adj,v,visited,recStack):returnTrue# Remove node from current DFS pathrecStack[u]=FalsereturnFalsedefisCyclic(V,edges):adj=[[]for_inrange(V)]# Create adjacency listforedgeinedges:adj[edge[0]].append(edge[1])visited=[False]*VrecStack=[False]*V# Check all componentsforiinrange(V):ifnotvisited[i]anddfs(adj,i,visited,recStack):returnTruereturnFalseif__name__=="__main__":V=4edges=[[0,1],[1,2],[2,0],[2,3]]print("true"ifisCyclic(V,edges)else"false")
C#
usingSystem;usingSystem.Collections.Generic;classGFG{publicstaticbooldfs(List<List<int>>adj,intu,bool[]visited,bool[]recStack){// Node is already in the current DFS pathif(recStack[u])returntrue;// Node is already visitedif(visited[u])returnfalse;visited[u]=true;recStack[u]=true;// Visit all adjacent nodesforeach(intvinadj[u]){if(dfs(adj,v,visited,recStack))returntrue;}// Remove node from current DFS pathrecStack[u]=false;returnfalse;}publicstaticboolisCyclic(intV,int[,]edges){List<List<int>>adj=newList<List<int>>();for(inti=0;i<V;i++)adj.Add(newList<int>());// Create adjacency listfor(inti=0;i<edges.GetLength(0);i++){adj[edges[i,0]].Add(edges[i,1]);}bool[]visited=newbool[V];bool[]recStack=newbool[V];// Check all componentsfor(inti=0;i<V;i++){if(!visited[i]&&dfs(adj,i,visited,recStack))returntrue;}returnfalse;}publicstaticvoidMain(){intV=4;int[,]edges={{0,1},{1,2},{2,0},{2,3}};Console.WriteLine(isCyclic(V,edges)?"true":"false");}}
JavaScript
functiondfs(adj,u,visited,recStack){// Node is already in the current DFS pathif(recStack[u])returntrue;// Node is already visitedif(visited[u])returnfalse;visited[u]=true;recStack[u]=true;// Visit all adjacent nodesfor(letvofadj[u]){if(dfs(adj,v,visited,recStack))returntrue;}// Remove node from current DFS pathrecStack[u]=false;returnfalse;}functionisCyclic(V,edges){letadj=Array.from({length:V},()=>[]);// Create adjacency listfor(letedgeofedges){adj[edge[0]].push(edge[1]);}letvisited=newArray(V).fill(false);letrecStack=newArray(V).fill(false);// Check all componentsfor(leti=0;i<V;i++){if(!visited[i]&&dfs(adj,i,visited,recStack))returntrue;}returnfalse;}// Driver codeletV=4;letedges=[[0,1],[1,2],[2,0],[2,3]];console.log(isCyclic(V,edges)?"true":"false");
Output
true
Using Topological Sorting - O(V + E) Time and O(V) Space
A directed graph has a topological ordering only if it is acyclic. We use Kahn’s Algorithm to find this ordering and check whether all vertices can be processed.
Kahn's Algorithm uses the indegree of each vertex, which is the number of incoming edges.
Calculate the indegree of each vertex.
Add all vertices with indegree 0 to the queue.
Process each vertex and decrease the indegree of its adjacent vertices.
Add a vertex to the queue when its indegree becomes 0.
Count the number of processed vertices.
If visited == V, the graph has no cycle.
If visited != V, the graph contains a cycle, as some vertices cannot be processed.
all vertices were processed successfully. Therefore, the graph does not contain a cycle.
Output:false
C++
#include<bits/stdc++.h>usingnamespacestd;boolisCyclic(intV,vector<vector<int>>&edges){vector<vector<int>>adj(V);// Create adjacency listfor(auto&edge:edges){adj[edge[0]].push_back(edge[1]);}// Array to store in-degree of each vertexvector<int>inDegree(V,0);queue<int>q;// Count of visited (processed) nodesintvisited=0;// Compute in-degrees of all verticesfor(intu=0;u<V;u++){for(intv:adj[u]){inDegree[v]++;}}// Add all vertices with in-degree 0 to the queuefor(intu=0;u<V;u++){if(inDegree[u]==0){q.push(u);}}// Perform BFS (Topological Sort)while(!q.empty()){intu=q.front();q.pop();visited++;// Reduce in-degree of neighborsfor(intv:adj[u]){inDegree[v]--;if(inDegree[v]==0){// Add to queue when in-degree becomes 0q.push(v);}}}// If visited nodes != total nodes, a cycle existsreturnvisited!=V;}intmain(){intV=4;vector<vector<int>>edges={{0,1},{0,2},{1,2},{2,3}};cout<<(isCyclic(V,edges)?"true":"false")<<endl;return0;}
Java
importjava.util.Queue;importjava.util.LinkedList;importjava.util.ArrayList;classGFG{publicstaticbooleanisCyclic(intV,int[][]edges){ArrayList<ArrayList<Integer>>adj=newArrayList<>();for(inti=0;i<V;i++){adj.add(newArrayList<>());}// Create adjacency listfor(int[]edge:edges){adj.get(edge[0]).add(edge[1]);}// Array to store in-degree of each vertexint[]inDegree=newint[V];Queue<Integer>q=newLinkedList<>();// Count of visited (processed) nodesintvisited=0;// Compute in-degrees of all verticesfor(intu=0;u<V;u++){for(intv:adj.get(u)){inDegree[v]++;}}// Add all vertices with in-degree 0 to the queuefor(intu=0;u<V;u++){if(inDegree[u]==0){q.add(u);}}// Perform BFS (Topological Sort)while(!q.isEmpty()){intu=q.poll();visited++;// Reduce in-degree of neighborsfor(intv:adj.get(u)){inDegree[v]--;if(inDegree[v]==0){// Add to queue when in-degree becomes 0q.add(v);}}}// If visited nodes != total nodes, a cycle existsreturnvisited!=V;}publicstaticvoidmain(String[]args){intV=4;int[][]edges={{0,1},{0,2},{1,2},{2,3}};System.out.println(isCyclic(V,edges)?"true":"false");}}
Python
fromcollectionsimportdequedefisCyclic(V,edges):adj=[[]for_inrange(V)]# Create adjacency listforedgeinedges:adj[edge[0]].append(edge[1])# Array to store in-degree of each vertexinDegree=[0]*Vq=deque()# Count of visited (processed) nodesvisited=0# Compute in-degrees of all verticesforuinrange(V):forvinadj[u]:inDegree[v]+=1# Add all vertices with in-degree 0 to the queueforuinrange(V):ifinDegree[u]==0:q.append(u)# Perform BFS (Topological Sort)whileq:u=q.popleft()visited+=1# Reduce in-degree of neighborsforvinadj[u]:inDegree[v]-=1ifinDegree[v]==0:# Add to queue when in-degree becomes 0q.append(v)# If visited nodes != total nodes, a cycle existsreturnvisited!=Vif__name__=="__main__":V=4edges=[[0,1],[0,2],[1,2],[2,3]]print("true"ifisCyclic(V,edges)else"false")
C#
usingSystem;usingSystem.Collections.Generic;classGFG{staticboolisCyclic(intV,int[,]edges){List<List<int>>adj=newList<List<int>>();for(inti=0;i<V;i++){adj.Add(newList<int>());}// Create adjacency listfor(inti=0;i<edges.GetLength(0);i++){adj[edges[i,0]].Add(edges[i,1]);}// Array to store in-degree of each vertexint[]inDegree=newint[V];Queue<int>q=newQueue<int>();// Count of visited (processed) nodesintvisited=0;// Compute in-degrees of all verticesfor(intu=0;u<V;u++){foreach(intvinadj[u]){inDegree[v]++;}}// Add all vertices with in-degree 0 to the queuefor(intu=0;u<V;u++){if(inDegree[u]==0){q.Enqueue(u);}}// Perform BFS (Topological Sort)while(q.Count>0){intu=q.Dequeue();visited++;// Reduce in-degree of neighborsforeach(intvinadj[u]){inDegree[v]--;if(inDegree[v]==0){// Add to queue when in-degree becomes 0q.Enqueue(v);}}}// If visited nodes != total nodes, a cycle existsreturnvisited!=V;}publicstaticvoidMain(){intV=4;int[,]edges={{0,1},{0,2},{1,2},{2,3}};Console.WriteLine(isCyclic(V,edges)?"true":"false");}}
JavaScript
functionisCyclic(V,edges){letadj=Array.from({length:V},()=>[]);// Create adjacency listfor(letedgeofedges){adj[edge[0]].push(edge[1]);}// Array to store in-degree of each vertexletinDegree=newArray(V).fill(0);letq=[];// Count of visited (processed) nodesletvisited=0;// Compute in-degrees of all verticesfor(letu=0;u<V;u++){for(letvofadj[u]){inDegree[v]++;}}// Add all vertices with in-degree 0 to the queuefor(letu=0;u<V;u++){if(inDegree[u]==0){q.push(u);}}// Perform BFS (Topological Sort)letfront=0;while(front<q.length){letu=q[front++];visited++;// Reduce in-degree of neighborsfor(letvofadj[u]){inDegree[v]--;if(inDegree[v]==0){// Add to queue when in-degree becomes 0q.push(v);}}}// If visited nodes != total nodes, a cycle existsreturnvisited!=V;}// Driver codeletV=4;letedges=[[0,1],[0,2],[1,2],[2,3]];console.log(isCyclic(V,edges)?"true":"false");