Given an adjacency list adj[][] representing an undirected graph, determine whether the graph contains a cycle/loop or not. A cycle is a path that starts and ends at the same vertex without repeating any edge.
Examples:
Input: adj[][]= [[1, 2], [0, 2], [0, 1, 3], [2]]
Output: true Explanation: There is a cycle 0 → 2 → 1 → 0
Input: adj[][] = [[1], [0, 2], [1, 3], [2]]
Output: false Explanation: There is no cycle in the given graph.
[Approach 1] Using Depth First Search - O(V+E) Time and O(V) Space
The idea is to use Depth First Search (DFS). When we start a DFS from a node, we visit all its connected neighbors one by one. If during this traversal, we reach a node that has already been visited before, it indicates that there might be a cycle, since we’ve come back to a previously explored vertex. However, there’s one important catch. In an undirected graph, every edge is bidirectional. That means, if there’s an edge from u → v, then there’s also an edge from v → u. So, while performing DFS, from u, we go to v. From v, we again see u as one of its neighbors. Since u is already visited, it might look like a cycle — but it’s not.
To avoid this issue, we keep track of the parent node — the node from which we reached the current node in DFS. When we move from u to v, we mark u as the parent of v. Now, while checking the neighbors of v, If a neighbor is not visited, we continue DFS for that node.If a neighbor is already visited and not equal to the parent, it means there’s another path that leads back to this node — and hence, a cycle exists.
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 Startsintmain(){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;letV=adj.length;// Recur for all the vertices adjacent to this vertexfor(leti=0;i<V;i++){if(adj[v][i]!==-1){letneighbor=i;// 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.functionisCycle(adj){letV=adj.length;// Mark all the vertices as not visitedletvisited=Array(V).fill(false);for(letu=0;u<V;u++){if(!visited[u]){if(dfs(u,adj,visited,-1))returntrue;}}returnfalse;}//Driver Code Starts// Driver codeletadj=[[1,2],[0,2],[0,1,3],[2]];console.log(isCycle(adj)?"true":"false");//Driver Code Ends
Output
true
[Approach 2] Using 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. BFS explores the graph level by level, ensuring that each node is visited in the shortest possible way. It also helps avoid deep recursion calls, making it more memory-efficient for large graphs.
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++
//Driver Code Starts#include<iostream>#include<vector>#include<queue>usingnamespacestd;//Driver Code Ends// 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;}//Driver Code Startsintmain(){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;importjava.util.LinkedList;importjava.util.Queue;publicclassGFG{//Driver Code Ends// 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;}//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.println(isCycle(adj)?"true":"false");}}//Driver Code Ends
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 componentreturnFalse#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 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;}//Driver Code Starts// 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");}}//Driver Code Ends
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;}// Example usage//Driver Code Startsletadj=[[1,2],[0,2],[0,1,3],[2]];console.log(isCycle(adj)?"true":"false");//Driver Code Ends