Given an undirected graph represented using an adjacency list adj[][]. Find the length of the shortest cycle in the graph. A cycle is a path that starts and ends at the same vertex without repeating any edge or vertex (except the start/end vertex). The shortest cycle is the cycle with the minimum number of edges. If the graph does not contain any cycle, return -1.
[Approach-1] Using BFS - O( V * (V+E)) Time and O(V) Space
The idea is to use Breadth-First Search (BFS) to detect the shortest cycle in a graph. We know that BFS works level by level, so while traversing, it always finds the shortest cycle first from the starting node. Therefore, we perform BFS from each vertex of the graph and finally take the minimum among all to get the overall shortest cycle length.
To achieve this, we perform BFS from each vertex in the graph:
For every vertex, start a BFS traversal.
Maintain a parent[] array to track the previous node (to avoid counting the same edge twice).
While performing BFS, if we reach a vertex that has already been visited and it is not the parent, a shortest cycle is found.
The current BFS level gives the length of that cycle, since BFS ensures minimal distance.
Repeat the above process for all vertices, keeping track of the minimum cycle length found.
C++
//Driver Code Starts#include<iostream>#include<vector>#include<climits>#include<queue>usingnamespacestd;//Driver Code Ends// BFS function to find shortest cycle starting from a given nodeintbfs(intstart,vector<vector<int>>&adj){intV=adj.size();// Distance and parent arraysvector<int>dist(V,(int)(1e9));vector<int>par(V,-1);queue<int>q;dist[start]=0;q.push(start);intans=INT_MAX;while(!q.empty()){intx=q.front();q.pop();for(intchild:adj[x]){// If not visited yetif(dist[child]==(int)(1e9)){dist[child]=dist[x]+1;par[child]=x;q.push(child);}// If already visited and not the parent, cycle foundelseif(par[x]!=child&&par[child]!=x){ans=min(ans,dist[x]+dist[child]+1);}}}returnans;}// Function to find length of shortest cycle in the graphintshortCycle(vector<vector<int>>&adj){intV=adj.size();intans=INT_MAX;// Run BFS from every vertexfor(inti=0;i<V;i++){ans=min(ans,bfs(i,adj));}// If no cycle foundif(ans==INT_MAX)return-1;returnans;}//Driver Code Startsintmain(){vector<vector<int>>adj={{5,6},{4,5,6},{3,6},{2,4},{1,3},{0,1},{0,1,2}};cout<<shortCycle(adj);return0;}//Driver Code Ends
Java
//Driver Code Startsimportjava.util.Queue;importjava.util.LinkedList;importjava.util.ArrayList;importjava.util.Arrays;importjava.lang.Integer;publicclassGFG{//Driver Code Ends// BFS function to find shortest cycle starting from a given nodestaticintbfs(intstart,ArrayList<ArrayList<Integer>>adj){intV=adj.size();// Distance and parent arraysint[]dist=newint[V];int[]par=newint[V];Arrays.fill(dist,(int)1e9);Arrays.fill(par,-1);Queue<Integer>q=newLinkedList<>();dist[start]=0;q.add(start);intans=Integer.MAX_VALUE;while(!q.isEmpty()){intx=q.poll();for(intchild:adj.get(x)){// If not visited yetif(dist[child]==(int)1e9){dist[child]=dist[x]+1;par[child]=x;q.add(child);}// If already visited and not the parent, cycle foundelseif(par[x]!=child&&par[child]!=x){ans=Math.min(ans,dist[x]+dist[child]+1);}}}returnans;}// Function to find length of shortest cycle in the graphstaticintshortCycle(ArrayList<ArrayList<Integer>>adj){intV=adj.size();intans=Integer.MAX_VALUE;// Run BFS from every vertexfor(inti=0;i<V;i++){ans=Math.min(ans,bfs(i,adj));}// If no cycle foundif(ans==Integer.MAX_VALUE)return-1;returnans;}//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=7;ArrayList<ArrayList<Integer>>adj=newArrayList<>();// Create empty adjacency listfor(inti=0;i<V;i++)adj.add(newArrayList<>());addEdge(adj,0,5);addEdge(adj,0,6);addEdge(adj,1,4);addEdge(adj,1,5);addEdge(adj,1,6);addEdge(adj,2,3);addEdge(adj,2,6);addEdge(adj,3,4);addEdge(adj,4,1);addEdge(adj,5,0);addEdge(adj,5,1);addEdge(adj,6,0);addEdge(adj,6,1);addEdge(adj,6,2);System.out.println(shortCycle(adj));}}//Driver Code Ends
Python
#Driver Code Startsfromcollectionsimportdequeimportsys#Driver Code Ends# BFS function to find shortest cycle starting from a given nodedefbfs(start,adj):V=len(adj)# Distance and parent arraysdist=[int(1e9)]*Vpar=[-1]*Vq=deque()dist[start]=0q.append(start)ans=sys.maxsizewhileq:x=q.popleft()forchildinadj[x]:# If not visited yetifdist[child]==int(1e9):dist[child]=dist[x]+1par[child]=xq.append(child)# If already visited and not the parent, cycle foundelifpar[x]!=childandpar[child]!=x:ans=min(ans,dist[x]+dist[child]+1)returnans# Function to find length of shortest cycle in the graphdefshortCycle(adj):V=len(adj)ans=sys.maxsize# Run BFS from every vertexforiinrange(V):ans=min(ans,bfs(i,adj))# If no cycle foundifans==sys.maxsize:return-1returnans#Driver Code Startsif__name__=="__main__":adj=[[5,6],[4,5,6],[3,6],[2,4],[1,3],[0,1],[0,1,2]]print(shortCycle(adj))#Driver Code Ends
C#
//Driver Code StartsusingSystem;usingSystem.Collections.Generic;publicclassGFG{//Driver Code Ends// BFS function to find shortest cycle starting from a given nodestaticintbfs(intstart,List<List<int>>adj){intV=adj.Count;// Distance and parent arraysint[]dist=newint[V];int[]par=newint[V];for(inti=0;i<V;i++){dist[i]=(int)1e9;par[i]=-1;}Queue<int>q=newQueue<int>();dist[start]=0;q.Enqueue(start);intans=int.MaxValue;while(q.Count>0){intx=q.Dequeue();foreach(intchildinadj[x]){// If not visited yetif(dist[child]==(int)1e9){dist[child]=dist[x]+1;par[child]=x;q.Enqueue(child);}// If already visited and not the parent, cycle foundelseif(par[x]!=child&&par[child]!=x){ans=Math.Min(ans,dist[x]+dist[child]+1);}}}returnans;}// Function to find length of shortest cycle in the graphstaticintshortCycle(List<List<int>>adj){intV=adj.Count;intans=int.MaxValue;// Run BFS from every vertexfor(inti=0;i<V;i++){ans=Math.Min(ans,bfs(i,adj));}// If no cycle foundif(ans==int.MaxValue)return-1;returnans;}//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);}publicstaticvoidMain(){intV=7;List<List<int>>adj=newList<List<int>>();// Create empty adjacency listfor(inti=0;i<V;i++)adj.Add(newList<int>());// Add edgesaddEdge(adj,0,5);addEdge(adj,0,6);addEdge(adj,1,4);addEdge(adj,1,5);addEdge(adj,1,6);addEdge(adj,2,3);addEdge(adj,2,6);addEdge(adj,3,4);addEdge(adj,4,1);addEdge(adj,5,0);addEdge(adj,5,1);addEdge(adj,6,0);addEdge(adj,6,1);addEdge(adj,6,2);Console.WriteLine(shortCycle(adj));}}//Driver Code Ends
JavaScript
//Driver Code StartsconstDeque=require("denque");//Driver Code Ends// BFS function to find shortest cycle starting from a given nodefunctionbfs(start,adj){constV=adj.length;// Distance and parent arraysletdist=newArray(V).fill(1e9);letpar=newArray(V).fill(-1);constq=newDeque();dist[start]=0;q.push(start);letans=Number.MAX_SAFE_INTEGER;while(q.length>0){letx=q.shift();for(letchildofadj[x]){// If not visited yetif(dist[child]===1e9){dist[child]=dist[x]+1;par[child]=x;q.push(child);}// If already visited and not the parent, cycle foundelseif(par[x]!==child&&par[child]!==x){ans=Math.min(ans,dist[x]+dist[child]+1);}}}returnans;}// Function to find length of shortest cycle in the graphfunctionshortCycle(adj){constV=adj.length;letans=Number.MAX_SAFE_INTEGER;// Run BFS from every vertexfor(leti=0;i<V;i++){ans=Math.min(ans,bfs(i,adj));}// If no cycle foundif(ans===Number.MAX_SAFE_INTEGER)return-1;returnans;}//Driver Code Starts// Driver codeconstadj=[[5,6],[4,5,6],[3,6],[2,4],[1,3],[0,1],[0,1,2]];console.log(shortCycle(adj));//Driver Code Ends
Output
4
[Approach-2] Using Edge Removal - O(E*(V+E)) Time and O(V+E) Space
The idea behind this approach is by temporarily removing each edge one by one and then using BFS to check if the two vertices connected by that edge are still reachable. If, after removing an edge (u, v), we can still reach v from u using BFS, then there exists another path between them — which means a cycle is formed. The length of this cycle will be equal to the shortest path distance between u and v (found using BFS) plus one (for the removed edge itself). We repeat this process for every edge in the graph, compute the cycle length for each, and take the minimum among them as the shortest cycle length.
C++
//Driver Code Starts#include<iostream>#include<vector>#include<queue>#include<climits>usingnamespacestd;//Driver Code EndsintshortCycle(vector<vector<int>>&adj){intV=adj.size();intans=INT_MAX;// Collect all unique edges (u < v to avoid duplicates)vector<vector<int>>edges;for(intu=0;u<V;u++){for(intv:adj[u]){if(u<v)edges.push_back({u,v});}}// For each edge (u, v), perform BFS ignoring that edgefor(auto&e:edges){intu=e[0],v=e[1];vector<int>dist(V,-1);queue<int>q;// Start BFS from node udist[u]=0;q.push(u);while(!q.empty()){intnode=q.front();q.pop();for(intnei:adj[node]){// Skip the removed edge (u, v)if((node==u&&nei==v)||(node==v&&nei==u))continue;// If not visited, update distance and push to queueif(dist[nei]==-1){dist[nei]=dist[node]+1;q.push(nei);}}}// If v is reachable from u, we found a cycleif(dist[v]!=-1)ans=min(ans,dist[v]+1);}// If no cycle is found, return -1return(ans==INT_MAX)?-1:ans;}//Driver Code Startsintmain(){// Given adjacency listvector<vector<int>>adj={{5,6},{4,5,6},{3,6},{2,4},{1,3},{0,1},{0,1,2}};// Call the functionintresult=shortCycle(adj);cout<<result<<endl;return0;}//Driver Code Ends
Java
//Driver Code Startsimportjava.util.ArrayList;importjava.util.Queue;importjava.util.LinkedList;importjava.util.Arrays;publicclassGFG{//Driver Code Ends// Function to find the shortest cycle in an undirected graphpublicstaticintshortCycle(ArrayList<ArrayList<Integer>>adj){intV=adj.size();intans=Integer.MAX_VALUE;// Collect all unique edges (u < v to avoid duplicates)ArrayList<ArrayList<Integer>>edges=newArrayList<>();for(intu=0;u<V;u++){for(intv:adj.get(u)){if(u<v){ArrayList<Integer>edge=newArrayList<>();edge.add(u);edge.add(v);edges.add(edge);}}}// For each edge (u, v), perform BFS ignoring that edgefor(ArrayList<Integer>e:edges){intu=e.get(0),v=e.get(1);int[]dist=newint[V];Arrays.fill(dist,-1);Queue<Integer>q=newLinkedList<>();// Start BFS from node udist[u]=0;q.add(u);while(!q.isEmpty()){intnode=q.poll();for(intnei:adj.get(node)){// Skip the removed edge (u, v)if((node==u&&nei==v)||(node==v&&nei==u))continue;// If not visited, update distance and push to queueif(dist[nei]==-1){dist[nei]=dist[node]+1;q.add(nei);}}}// If v is reachable from u, we found a cycleif(dist[v]!=-1)ans=Math.min(ans,dist[v]+1);}// If no cycle is found, return -1return(ans==Integer.MAX_VALUE)?-1:ans;}//Driver Code Starts// Helper function to add an undirected edgepublicstaticvoidaddEdge(ArrayList<ArrayList<Integer>>adj,intu,intv){adj.get(u).add(v);adj.get(v).add(u);}publicstaticvoidmain(String[]args){intV=7;// Create adjacency listArrayList<ArrayList<Integer>>adj=newArrayList<>();for(inti=0;i<V;i++){adj.add(newArrayList<>());}// Add edgesaddEdge(adj,0,5);addEdge(adj,0,6);addEdge(adj,1,4);addEdge(adj,1,5);addEdge(adj,1,6);addEdge(adj,2,3);addEdge(adj,2,6);addEdge(adj,3,4);addEdge(adj,4,1);addEdge(adj,5,0);addEdge(adj,6,2);addEdge(adj,6,1);addEdge(adj,6,0);// Call the functionintresult=shortCycle(adj);System.out.println(result);}}//Driver Code Ends
Python
#Driver Code Startsfromcollectionsimportdequeimportsys#Driver Code EndsdefshortCycle(adj):V=len(adj)ans=sys.maxsize# Collect all unique edges (u < v to avoid duplicates)edges=[]foruinrange(V):forvinadj[u]:ifu<v:edges.append([u,v])# For each edge (u, v), perform BFS ignoring that edgeforeinedges:u,v=e[0],e[1]dist=[-1]*Vq=deque()# Start BFS from node udist[u]=0q.append(u)whileq:node=q.popleft()forneiinadj[node]:# Skip the removed edge (u, v)if(node==uandnei==v)or(node==vandnei==u):continue# If not visited, update distance and push to queueifdist[nei]==-1:dist[nei]=dist[node]+1q.append(nei)# If v is reachable from u, we found a cycleifdist[v]!=-1:ans=min(ans,dist[v]+1)# If no cycle is found, return -1return-1ifans==sys.maxsizeelseans#Driver Code Startsif__name__=="__main__":# Given adjacency listadj=[[5,6],[4,5,6],[3,6],[2,4],[1,3],[0,1],[0,1,2]]# Call the functionresult=shortCycle(adj)print(result)#Driver Code Ends
C#
//Driver Code StartsusingSystem;usingSystem.Collections.Generic;publicclassGFG{//Driver Code Ends// Function to find the shortest cycle in an undirected graphpublicstaticintshortCycle(List<List<int>>adj){intV=adj.Count;intans=int.MaxValue;// Collect all unique edges (u < v to avoid duplicates)List<List<int>>edges=newList<List<int>>();for(intu=0;u<V;u++){foreach(intvinadj[u]){if(u<v){edges.Add(newList<int>{u,v});}}}// For each edge (u, v), perform BFS ignoring that edgeforeach(vareinedges){intu=e[0],v=e[1];int[]dist=newint[V];Array.Fill(dist,-1);Queue<int>q=newQueue<int>();// Start BFS from node udist[u]=0;q.Enqueue(u);while(q.Count>0){intnode=q.Dequeue();foreach(intneiinadj[node]){// Skip the removed edge (u, v)if((node==u&&nei==v)||(node==v&&nei==u))continue;// If not visited, update distance and push to queueif(dist[nei]==-1){dist[nei]=dist[node]+1;q.Enqueue(nei);}}}// If v is reachable from u, we found a cycleif(dist[v]!=-1)ans=Math.Min(ans,dist[v]+1);}// If no cycle is found, return -1return(ans==int.MaxValue)?-1:ans;}//Driver Code Starts// Helper function to add an undirected edgepublicstaticvoidaddEdge(List<List<int>>adj,intu,intv){adj[u].Add(v);adj[v].Add(u);}publicstaticvoidMain(){intV=7;// Create adjacency listList<List<int>>adj=newList<List<int>>();for(inti=0;i<V;i++){adj.Add(newList<int>());}// Add edgesaddEdge(adj,0,5);addEdge(adj,0,6);addEdge(adj,1,4);addEdge(adj,1,5);addEdge(adj,1,6);addEdge(adj,2,3);addEdge(adj,2,6);addEdge(adj,3,4);addEdge(adj,4,1);addEdge(adj,5,0);addEdge(adj,6,2);addEdge(adj,6,1);addEdge(adj,6,0);// Call the functionintresult=shortCycle(adj);Console.WriteLine(result);}}//Driver Code Ends
JavaScript
functionshortCycle(adj){constV=adj.length;letans=Number.MAX_SAFE_INTEGER;// Collect all unique edges (u < v to avoid duplicates)constedges=[];for(letu=0;u<V;u++){for(letvofadj[u]){if(u<v)edges.push([u,v]);}}// For each edge (u, v), perform BFS ignoring that edgefor(leteofedges){constu=e[0],v=e[1];constdist=newArray(V).fill(-1);constq=[];// Start BFS from node udist[u]=0;q.push(u);while(q.length>0){constnode=q.shift();for(letneiofadj[node]){// Skip the removed edge (u, v)if((node===u&&nei===v)||(node===v&&nei===u))continue;// If not visited, update distance and push to queueif(dist[nei]===-1){dist[nei]=dist[node]+1;q.push(nei);}}}// If v is reachable from u, we found a cycleif(dist[v]!==-1)ans=Math.min(ans,dist[v]+1);}// If no cycle is found, return -1return(ans===Number.MAX_SAFE_INTEGER)?-1:ans;}//Driver Code//Driver Code Starts// Given adjacency listconstadj=[[5,6],[4,5,6],[3,6],[2,4],[1,3],[0,1],[0,1,2]];// Call the functionconstresult=shortCycle(adj);console.log(result);//Driver Code Ends
Output
4
Why not dfs?
DFS (Depth-First Search) goes as deep as possible before backtracking. This can easily cause it to find longer cycles first, because it doesn’t explore in increasing order of path length. DFS can detect if a cycle exists but it cannot ensure that the first cycle found is the shortest one.