The idea is to use Depth First Search (DFS) where we visit a vertex and then explore its adjacent vertices. If we reach a vertex that has already been visited, it may indicate a cycle.
However, in an undirected graph, when DFS moves from u to v, visiting u again from v does not mean that a cycle exists. To handle this, we keep track of the parent of each vertex. The parent is the vertex from which the current vertex was reached during DFS..
If during traversal we encounter a node that is already visited and is not the parent of the current node, it means we’ve found a cycle in the graph.
Mark the current vertex as visited and check all its adjacent vertices.
If an adjacent vertex is not visited, continue DFS from that vertex and set the current vertex as its parent.
If an adjacent vertex is already visited and is not the parent of the current vertex, a cycle exists.
If all vertices are explored without finding a cycle, the graph does not contain a cycle.
C++
//Driver Code Starts#include<iostream>#include<vector>usingnamespacestd;//Driver Code Endsbooldfs(intv,vector<vector<int>>&adj,vector<bool>&visited,intparent){// Mark the current node as visitedvisited[v]=true;// Recur for all the vertices adjacent to this vertexfor(inti:adj[v]){// If an adjacent vertex is not visited, //then recur for that adjacentif(!visited[i]){if(dfs(i,adj,visited,v))returntrue;}// If an adjacent vertex is visited and is not//parent of current vertex,// then there exists a cycle in the graph.elseif(i!=parent)returntrue;}returnfalse;}// Returns true if the graph contains a cycle, else false.boolisCycle(vector<vector<int>>&adj){intV=adj.size();// Mark all the vertices as not visitedvector<bool>visited(V,false);for(intu=0;u<V;u++){if(!visited[u]){if(dfs(u,adj,visited,-1))returntrue;}}returnfalse;//Driver Code Starts}intmain(){vector<vector<int>>adj={{1,2},{0,2},{0,1,3},{2}};isCycle(adj)?cout<<"true":cout<<"false";return0;}//Driver Code Ends
Java
//Driver Code Startsimportjava.util.ArrayList;publicclassGFG{//Driver Code Endsstaticbooleandfs(intv,ArrayList<ArrayList<Integer>>adj,boolean[]visited,intparent){// Mark the current node as visitedvisited[v]=true;// Recur for all the vertices adjacent to this vertexfor(intneighbor:adj.get(v)){// If an adjacent vertex is not visited, // then recur for that adjacentif(!visited[neighbor]){if(dfs(neighbor,adj,visited,v))returntrue;}// If an adjacent vertex is visited and is not// parent of current vertex,// then there exists a cycle in the graph.elseif(neighbor!=parent)returntrue;}returnfalse;}// Returns true if the graph contains a cycle, else false.staticbooleanisCycle(ArrayList<ArrayList<Integer>>adj){intV=adj.size();// Mark all the vertices as not visitedboolean[]visited=newboolean[V];for(intu=0;u<V;u++){if(!visited[u]){if(dfs(u,adj,visited,-1))returntrue;}}returnfalse;}//Driver Code Starts// Function to add an edge to the adjacency liststaticvoidaddEdge(ArrayList<ArrayList<Integer>>adj,intu,intv){adj.get(u).add(v);adj.get(v).add(u);}publicstaticvoidmain(String[]args){intV=4;ArrayList<ArrayList<Integer>>adj=newArrayList<>();for(inti=0;i<V;i++)adj.add(newArrayList<>());// Add edgesaddEdge(adj,0,1);addEdge(adj,0,2);addEdge(adj,1,2);addEdge(adj,2,3);System.out.print(isCycle(adj)?"true":"false");}}//Driver Code Ends
Python
defdfs(v,adj,visited,parent):# Mark the current node as visitedvisited[v]=True# Recur for all the vertices adjacent to this vertexforneighborinadj[v]:# If an adjacent vertex is not visited, # then recur for that adjacentifnotvisited[neighbor]:ifdfs(neighbor,adj,visited,v):returnTrue# If an adjacent vertex is visited and is not# parent of current vertex,# then there exists a cycle in the graph.elifneighbor!=parent:returnTruereturnFalse# Returns true if the graph contains a cycle, else false.defisCycle(adj):V=len(adj)# Mark all the vertices as not visitedvisited=[False]*Vforuinrange(V):ifnotvisited[u]:ifdfs(u,adj,visited,-1):returnTruereturnFalse#Driver Code Startsif__name__=="__main__":adj=[[1,2],[0,2],[0,1,3],[2]]print("true"ifisCycle(adj)else"false")#Driver Code Ends
C#
//Driver Code StartsusingSystem;usingSystem.Collections.Generic;classGFG{//Driver Code Ends// Function to add an edge to the adjacency liststaticvoidaddEdge(List<List<int>>adj,intu,intv){adj[u].Add(v);adj[v].Add(u);}staticbooldfs(intv,List<List<int>>adj,bool[]visited,intparent){// Mark the current node as visitedvisited[v]=true;// Recur for all the vertices adjacent to this vertexforeach(intneighborinadj[v]){// If an adjacent vertex is not visited, // then recur for that adjacentif(!visited[neighbor]){if(dfs(neighbor,adj,visited,v))returntrue;}// If an adjacent vertex is visited and is not// parent of current vertex,// then there exists a cycle in the graph.elseif(neighbor!=parent)returntrue;}returnfalse;}// Returns true if the graph contains a cycle, else false.staticboolisCycle(List<List<int>>adj){intV=adj.Count;// Mark all the vertices as not visitedbool[]visited=newbool[V];for(intu=0;u<V;u++){if(!visited[u]){if(dfs(u,adj,visited,-1))returntrue;}}returnfalse;}//Driver Code StartsstaticvoidMain(){intV=4;List<List<int>>adj=newList<List<int>>();for(inti=0;i<V;i++)adj.Add(newList<int>());// Add edgesaddEdge(adj,0,1);addEdge(adj,0,2);addEdge(adj,1,2);addEdge(adj,2,3);Console.Write(isCycle(adj)?"true":"false");}}//Driver Code Ends
JavaScript
functiondfs(v,adj,visited,parent){// Mark the current node as visitedvisited[v]=true;// Recur for all adjacent verticesfor(letneighborofadj[v]){// If an adjacent vertex is not visitedif(!visited[neighbor]){if(dfs(neighbor,adj,visited,v))returntrue;}// If an adjacent vertex is visited and is not the parentelseif(neighbor!==parent){returntrue;}}returnfalse;}// Returns true if the graph contains a cycle, else false.functionisCycle(adj){letV=adj.length;// Mark all vertices as unvisitedletvisited=Array(V).fill(false);for(letu=0;u<V;u++){if(!visited[u]){if(dfs(u,adj,visited,-1))returntrue;}}returnfalse;}// Driver codeletadj=[[1,2],[0,2],[0,1,3],[2]];console.log(isCycle(adj)?"true":"false");
Output
true
Breadth First Search - O(V+E) Time and O(V) Space
The idea is quite similar to DFS-based cycle detection, but here we use Breadth First Search (BFS) instead of recursion.
In BFS, we also maintain a visited array to mark nodes that have been explored and a parent tracker to remember from which node we reached the current one.
If during traversal we encounter a node that is already visited and is not the parent of the current node, it means we’ve found a cycle in the graph.
C++
#include<iostream>#include<vector>#include<queue>usingnamespacestd;// Function to perform BFS from node 'start' to detect cycleboolbfs(intstart,vector<vector<int>>&adj,vector<bool>&visited){// Queue stores {current node, parent node}queue<pair<int,int>>q;// Start node has no parentq.push({start,-1});visited[start]=true;while(!q.empty()){intnode=q.front().first;intparent=q.front().second;q.pop();// Traverse all neighbors of current nodefor(intneighbor:adj[node]){// If neighbor is not visited, mark it visited and push to queueif(!visited[neighbor]){visited[neighbor]=true;q.push({neighbor,node});}// If neighbor is visited and not parent, a cycle is detectedelseif(neighbor!=parent){returntrue;}}}// No cycle found starting from this nodereturnfalse;}// Function to check if the undirected graph contains a cycleboolisCycle(vector<vector<int>>&adj){intV=adj.size();// Keep track of visited verticesvector<bool>visited(V,false);// Perform BFS from every unvisited nodefor(inti=0;i<V;i++){if(!visited[i]){// If BFS finds a cycleif(bfs(i,adj,visited)){returntrue;}}}// If no cycle is found in any componentreturnfalse;}intmain(){vector<vector<int>>adj={{1,2},{0,2},{0,1,3},{2}};isCycle(adj)?cout<<"true":cout<<"false";return0;}
Java
importjava.util.ArrayList;importjava.util.LinkedList;importjava.util.Queue;publicclassGFG{// Function to perform BFS from node 'start' to detect cyclestaticbooleanbfs(intstart,ArrayList<ArrayList<Integer>>adj,boolean[]visited){// Queue stores {current node, parent node}Queue<int[]>q=newLinkedList<>();// Start node has no parentq.add(newint[]{start,-1});visited[start]=true;while(!q.isEmpty()){intnode=q.peek()[0];intparent=q.peek()[1];q.poll();// Traverse all neighbors of current nodefor(intneighbor:adj.get(node)){// If neighbor is not visited, mark it visited and push to queueif(!visited[neighbor]){visited[neighbor]=true;q.add(newint[]{neighbor,node});}// If neighbor is visited and not parent, a cycle is detectedelseif(neighbor!=parent){returntrue;}}}// No cycle found starting from this nodereturnfalse;}// Function to check if the undirected graph contains a cyclestaticbooleanisCycle(ArrayList<ArrayList<Integer>>adj){intV=adj.size();// Keep track of visited verticesboolean[]visited=newboolean[V];// Perform BFS from every unvisited nodefor(inti=0;i<V;i++){if(!visited[i]){// If BFS finds a cycleif(bfs(i,adj,visited)){returntrue;}}}// If no cycle is found in any componentreturnfalse;}// Function to add an edge to the adjacency liststaticvoidaddEdge(ArrayList<ArrayList<Integer>>adj,intu,intv){adj.get(u).add(v);adj.get(v).add(u);}publicstaticvoidmain(String[]args){intV=4;ArrayList<ArrayList<Integer>>adj=newArrayList<>();for(inti=0;i<V;i++){adj.add(newArrayList<>());}// Add edgesaddEdge(adj,0,1);addEdge(adj,0,2);addEdge(adj,1,2);addEdge(adj,2,3);System.out.println(isCycle(adj)?"true":"false");}}
Python
fromcollectionsimportdeque# Function to perform BFS from node 'start' to detect cycledefbfs(start,adj,visited):# Queue stores [current node, parent node]q=deque()# Start node has no parentq.append([start,-1])visited[start]=Truewhileq:node=q[0][0]parent=q[0][1]q.popleft()# Traverse all neighbors of current nodeforneighborinadj[node]:# If neighbor is not visited, mark it visited and push to queueifnotvisited[neighbor]:visited[neighbor]=Trueq.append([neighbor,node])# If neighbor is visited and not parent, a cycle is detectedelifneighbor!=parent:returnTrue# No cycle found starting from this nodereturnFalse# Function to check if the undirected graph contains a cycledefisCycle(adj):V=len(adj)# Keep track of visited verticesvisited=[False]*V# Perform BFS from every unvisited nodeforiinrange(V):ifnotvisited[i]:# If BFS finds a cycleifbfs(i,adj,visited):returnTrue# If no cycle is found in any componentreturnFalseif__name__=="__main__":adj=[[1,2],[0,2],[0,1,3],[2]]print("true"ifisCycle(adj)else"false")
C#
usingSystem;usingSystem.Collections.Generic;classGFG{// Function to perform BFS from node 'start' to detect cyclestaticboolbfs(intstart,List<List<int>>adj,bool[]visited){// Queue stores {current node, parent node}Queue<int[]>q=newQueue<int[]>();// Start node has no parentq.Enqueue(newint[]{start,-1});visited[start]=true;while(q.Count>0){intnode=q.Peek()[0];intparent=q.Peek()[1];q.Dequeue();// Traverse all neighbors of current nodeforeach(intneighborinadj[node]){// If neighbor is not visited, mark it visited and push to queueif(!visited[neighbor]){visited[neighbor]=true;q.Enqueue(newint[]{neighbor,node});}// If neighbor is visited and not parent, a cycle is detectedelseif(neighbor!=parent){returntrue;}}}// No cycle found starting from this nodereturnfalse;}// Function to check if the undirected graph contains a cyclestaticboolisCycle(List<List<int>>adj){intV=adj.Count;// Keep track of visited verticesbool[]visited=newbool[V];// Perform BFS from every unvisited nodefor(inti=0;i<V;i++){if(!visited[i]){// If BFS finds a cycleif(bfs(i,adj,visited)){returntrue;}}}// If no cycle is found in any componentreturnfalse;}// Function to add an edge to the adjacency liststaticvoidaddEdge(List<List<int>>adj,intu,intv){adj[u].Add(v);adj[v].Add(u);}staticvoidMain(){intV=4;List<List<int>>adj=newList<List<int>>();for(inti=0;i<V;i++)adj.Add(newList<int>());// Add edgesaddEdge(adj,0,1);addEdge(adj,0,2);addEdge(adj,1,2);addEdge(adj,2,3);Console.WriteLine(isCycle(adj)?"true":"false");}}
JavaScript
constDeque=require("denque");// Function to perform BFS from node 'start' to detect cyclefunctionbfs(start,adj,visited){// Queue stores [current node, parent node]letq=newDeque();// Start node has no parentq.push([start,-1]);visited[start]=true;while(q.length>0){let[node,parent]=q.shift();// pop from front// Traverse all neighbors of current nodefor(letneighborofadj[node]){// If neighbor is not visited, mark visited and enqueueif(!visited[neighbor]){visited[neighbor]=true;q.push([neighbor,node]);}// If neighbor is visited and not the parent, cycle foundelseif(neighbor!==parent){returntrue;}}}// No cycle found starting from this nodereturnfalse;}// Function to check if the undirected graph contains a cyclefunctionisCycle(adj){letV=adj.length;letvisited=Array(V).fill(false);// Perform BFS from every unvisited nodefor(leti=0;i<V;i++){if(!visited[i]){if(bfs(i,adj,visited)){returntrue;}}}// No cycle found in any componentreturnfalse;}// Driver codeletadj=[[1,2],[0,2],[0,1,3],[2]];console.log(isCycle(adj)?"true":"false");