Given an undirected, weighted graph with V vertices numbered from 0 to V-1, and E edges represented as a 2D array edges[][], where each element edges[i] = [u, v, w] denotes an edge between nodes u and v with weight w, and all edge weights are positive integers, your task is to find the minimum weight cycle in the graph.
Note: A cycle in a graph is a path that starts and ends at the same vertex without repeating any edges or vertices (except the starting/ending vertex). The minimum weight cycle is the one among all possible cycles that has the smallest total sum of edge weights
Find all cycles in the graph using DFS, and while exploring each cycle, keep track of its total weight. Update and maintain the minimum weight found across all such cycles.
C++
//Driver Code Starts#include<algorithm>#include<climits>#include<iostream>#include<vector>usingnamespacestd;// Construct the adjacency listvector<vector<vector<int>>>constructAdj(intV,vector<vector<int>>&edges){vector<vector<vector<int>>>adj(V);for(auto&edge:edges){intu=edge[0],v=edge[1],w=edge[2];adj[u].push_back({v,w});adj[v].push_back({u,w});}returnadj;}//Driver Code EndsintminCycle;// DFS to explore cycles and track their weightsvoiddfs(intu,intparent,vector<vector<vector<int>>>&adj,vector<bool>&visited,vector<int>&path,vector<int>&weights,intcurrWeight){visited[u]=true;path.push_back(u);for(auto&edge:adj[u]){intv=edge[0];intw=edge[1];// avoid going back to the parentif(v==parent)continue;if(!visited[v]){weights.push_back(w);dfs(v,u,adj,visited,path,weights,currWeight+w);weights.pop_back();}else{// Found a cycleautoit=find(path.begin(),path.end(),v);if(it!=path.end()){intcycleWeight=0;intidx=it-path.begin();for(inti=idx;i<weights.size();i++){cycleWeight+=weights[i];}// add the closing edgecycleWeight+=w;minCycle=min(minCycle,cycleWeight);}}}path.pop_back();visited[u]=false;}intfindMinCycle(intV,vector<vector<int>>&edges){vector<vector<vector<int>>>adj=constructAdj(V,edges);minCycle=INT_MAX;vector<bool>visited(V,false);vector<int>path,weights;for(inti=0;i<V;i++){dfs(i,-1,adj,visited,path,weights,0);}returnminCycle;}//Driver Code Startsintmain(){intV=5;vector<vector<int>>edges={{0,1,2},{1,2,2},{1,3,1},{1,4,1},{0,4,3},{2,3,4}};intresult=findMinCycle(V,edges);cout<<result<<endl;return0;}//Driver Code Ends
Java
//Driver Code Startsimportjava.util.*;publicclassSolution{// Construct the adjacency liststaticArrayList<ArrayList<int[]>>constructAdj(intV,int[][]edges){ArrayList<ArrayList<int[]>>adj=newArrayList<>();for(inti=0;i<V;i++)adj.add(newArrayList<>());for(int[]edge:edges){intu=edge[0],v=edge[1],w=edge[2];adj.get(u).add(newint[]{v,w});adj.get(v).add(newint[]{u,w});}returnadj;//Driver Code Ends}staticintminCycle;// DFS to explore cycles and track their weightsstaticvoiddfs(intu,intparent,ArrayList<ArrayList<int[]>>adj,boolean[]visited,ArrayList<Integer>path,ArrayList<Integer>weights,intcurrWeight){visited[u]=true;path.add(u);for(int[]edge:adj.get(u)){intv=edge[0];intw=edge[1];// avoid going back to the parentif(v==parent)continue;if(!visited[v]){weights.add(w);dfs(v,u,adj,visited,path,weights,currWeight+w);weights.remove(weights.size()-1);}else{// Found a cycleintidx=path.indexOf(v);if(idx!=-1){intcycleWeight=0;for(inti=idx;i<weights.size();i++){cycleWeight+=weights.get(i);}// add the closing edgecycleWeight+=w;minCycle=Math.min(minCycle,cycleWeight);}}}path.remove(path.size()-1);visited[u]=false;}staticintfindMinCycle(intV,int[][]edges){ArrayList<ArrayList<int[]>>adj=constructAdj(V,edges);minCycle=Integer.MAX_VALUE;boolean[]visited=newboolean[V];ArrayList<Integer>path=newArrayList<>();ArrayList<Integer>weights=newArrayList<>();for(inti=0;i<V;i++){dfs(i,-1,adj,visited,path,weights,0);}returnminCycle;}//Driver Code Startspublicstaticvoidmain(String[]args){intV=5;int[][]edges={{0,1,2},{1,2,2},{1,3,1},{1,4,1},{0,4,3},{2,3,4}};intresult=findMinCycle(V,edges);System.out.println(result);}}//Driver Code Ends
Python
#Driver Code Startsimportsys# Construct the adjacency listdefconstructAdj(V,edges):adj=[[]for_inrange(V)]foredgeinedges:u,v,w=edgeadj[u].append([v,w])adj[v].append([u,w])returnadj#Driver Code EndsminCycle=sys.maxsize# DFS to explore cycles and track their weightsdefdfs(u,parent,adj,visited,path,weights,currWeight):globalminCyclevisited[u]=Truepath.append(u)foredgeinadj[u]:v=edge[0]w=edge[1]# avoid going back to the parentifv==parent:continueifnotvisited[v]:weights.append(w)dfs(v,u,adj,visited,path,weights,currWeight+w)weights.pop()else:# Found a cycleifvinpath:idx=path.index(v)cycleWeight=sum(weights[idx:])+w# add the closing edgeminCycle=min(minCycle,cycleWeight)path.pop()visited[u]=FalsedeffindMinCycle(V,edges):globalminCycleadj=constructAdj(V,edges)minCycle=sys.maxsizevisited=[False]*Vpath=[]weights=[]foriinrange(V):dfs(i,-1,adj,visited,path,weights,0)returnminCycle#Driver Code Starts# MainV=5edges=[[0,1,2],[1,2,2],[1,3,1],[1,4,1],[0,4,3],[2,3,4]]result=findMinCycle(V,edges)print(result)#Driver Code Ends
C#
//Driver Code StartsusingSystem;usingSystem.Collections.Generic;classGfG{// Construct the adjacency liststaticList<List<int[]>>constructAdj(intV,int[,]edges){varadj=newList<List<int[]>>();for(inti=0;i<V;i++)adj.Add(newList<int[]>());for(inti=0;i<edges.GetLength(0);i++){intu=edges[i,0],v=edges[i,1],w=edges[i,2];adj[u].Add(newint[]{v,w});adj[v].Add(newint[]{u,w});}returnadj;}//Driver Code EndsstaticintminCycle;// DFS to explore cycles and track their weightsstaticvoiddfs(intu,intparent,List<List<int[]>>adj,bool[]visited,List<int>path,List<int>weights,intcurrWeight){visited[u]=true;path.Add(u);foreach(varedgeinadj[u]){intv=edge[0];intw=edge[1];// avoid going back to the parentif(v==parent)continue;if(!visited[v]){weights.Add(w);dfs(v,u,adj,visited,path,weights,currWeight+w);weights.RemoveAt(weights.Count-1);}else{// Found a cycleintidx=path.IndexOf(v);if(idx!=-1){intcycleWeight=0;for(inti=idx;i<weights.Count;i++){cycleWeight+=weights[i];}// add the closing edgecycleWeight+=w;minCycle=Math.Min(minCycle,cycleWeight);}}}path.RemoveAt(path.Count-1);visited[u]=false;}staticintfindMinCycle(intV,int[,]edges){varadj=constructAdj(V,edges);minCycle=int.MaxValue;varvisited=newbool[V];varpath=newList<int>();varweights=newList<int>();for(inti=0;i<V;i++){dfs(i,-1,adj,visited,path,weights,0);}returnminCycle;}//Driver Code StartspublicstaticvoidMain(){intV=5;int[,]edges={{0,1,2},{1,2,2},{1,3,1},{1,4,1},{0,4,3},{2,3,4}};intresult=findMinCycle(V,edges);Console.WriteLine(result);}}//Driver Code Ends
JavaScript
//Driver Code Starts// Construct the adjacency listfunctionconstructAdj(V,edges){constadj=Array.from({length:V},()=>[]);for(constedgeofedges){const[u,v,w]=edge;adj[u].push([v,w]);adj[v].push([u,w]);}returnadj;}//Driver Code EndsletminCycle=Number.MAX_SAFE_INTEGER;// DFS to explore cycles and track their weightsfunctiondfs(u,parent,adj,visited,path,weights,currWeight){visited[u]=true;path.push(u);for(constedgeofadj[u]){constv=edge[0];constw=edge[1];// avoid going back to the parentif(v===parent)continue;if(!visited[v]){weights.push(w);dfs(v,u,adj,visited,path,weights,currWeight+w);weights.pop();}else{// Found a cycleconstidx=path.indexOf(v);if(idx!==-1){letcycleWeight=0;for(leti=idx;i<weights.length;i++){cycleWeight+=weights[i];}// add the closing edgecycleWeight+=w;minCycle=Math.min(minCycle,cycleWeight);}}}path.pop();visited[u]=false;}functionfindMinCycle(V,edges){constadj=constructAdj(V,edges);minCycle=Number.MAX_SAFE_INTEGER;constvisited=Array(V).fill(false);constpath=[];constweights=[];for(leti=0;i<V;i++){dfs(i,-1,adj,visited,path,weights,0);}returnminCycle;}//Driver Code Starts// MainconstV=5;constedges=[[0,1,2],[1,2,2],[1,3,1],[1,4,1],[0,4,3],[2,3,4]];constresult=findMinCycle(V,edges);console.log(result);//Driver Code Ends
Output
6
Time Complexity: O(2V)The time complexity is exponential in the worst case (e.g. O(2V)) due to the large number of simple cycles, but in typical cases, especially for sparse graphs, it may behave closer to O(V×(V + E)) Space Complexity: O(V+E), as dominated by the storage for the graph (adjacency list) and the DFS auxiliary structures (visited array, path, weights, and recursion stack).
[Expected Approach] : Using Dijkstra's algorithm - O(E * (V + E) log V) Time and O(V+E) Space
To find the shortest cycle in the graph, we iterate over each edge (u,v,w)and temporarily remove it. The idea is that any edge might be part of the minimum weight cycle, so we check if a cycle can still be formed without it.
We then use Dijkstra's algorithm (or any shortest path algorithm) to find the shortest path from u to v while excluding the removed edge. If such a path exists, adding the removed edge back completes a cycle. The total weight of this cycle is the sum of the shortest path and the weight of the removed edge.
By repeating this process for every edge, we ensure that all possible cycles are considered, and we avoid redundant checks. Among all valid cycles found, we track and return the one with the minimum total weight. This method is both efficient and systematic for identifying the shortest cycle in a weighted, undirected graph.
Step by step Implementation:
First, construct the adjacency list representation of the graph based on the provided edges.
Iterate through each edge in the graph and temporarily exclude it during the calculations.
For each excluded edge, use Dijkstra's algorithm to compute the shortest path between the source and destination nodes.
After calculating the shortest distance, if it's not infinity, it means a path exists between the source and destination even without the excluded edge, forming a potential cycle.
Repeat the process for all edges and track the minimum cycle weight by adding the excluded edge's weight to the shortest path found
Illustration:
C++
//Driver Code Starts#include<bits/stdc++.h>usingnamespacestd;// Construct adjacency listvector<vector<vector<int>>>constructadj(intV,vector<vector<int>>&edges){vector<vector<vector<int>>>adj(V);for(auto&edge:edges){intu=edge[0],v=edge[1],w=edge[2];adj[u].push_back({v,w});adj[v].push_back({u,w});}returnadj;}//Driver Code Ends// find sortest path between src and dest.intshortestPath(intV,vector<vector<vector<int>>>&adj,intsrc,intdest){vector<int>dist(V,INT_MAX);dist[src]=0;// priority queuepriority_queue<pair<int,int>,vector<pair<int,int>>,greater<>>pq;pq.push({0,src});while(!pq.empty()){pair<int,int>top=pq.top();pq.pop();intd=top.first,u=top.second;if(d>dist[u])continue;for(auto&neighbor:adj[u]){intv=neighbor[0];intw=neighbor[1];// Skip the ignored edgeif((u==src&&v==dest)||(u==dest&&v==src))continue;if(dist[v]>dist[u]+w){dist[v]=dist[u]+w;pq.push({dist[v],v});}}}returndist[dest];}// Function to find the minimum weight cycle in the graphintfindMinCycle(intV,vector<vector<int>>&edges){vector<vector<vector<int>>>adj=constructadj(V,edges);intminCycle=INT_MAX;for(constauto&edge:edges){intu=edge[0];intv=edge[1];intw=edge[2];intdist=shortestPath(V,adj,u,v);if(dist!=INT_MAX){minCycle=min(minCycle,dist+w);}}returnminCycle;}//Driver Code Starts// Driver codeintmain(){intV=5;vector<vector<int>>edges={{0,1,2},{1,2,2},{1,3,1},{1,4,1},{0,4,3},{2,3,4}};cout<<findMinCycle(V,edges)<<endl;return0;}//Driver Code Ends
Java
//Driver Code Startsimportjava.util.*;publicclassMinimumCycle{// Construct adjacency list publicstaticArrayList<ArrayList<int[]>>constructAdj(intV,int[][]edges){ArrayList<ArrayList<int[]>>adj=newArrayList<>();for(inti=0;i<V;i++)adj.add(newArrayList<>());for(int[]edge:edges){intu=edge[0],v=edge[1],w=edge[2];adj.get(u).add(newint[]{v,w});adj.get(v).add(newint[]{u,w});}returnadj;}//Driver Code Ends// shortest path from src to destpublicstaticintshortestPath(intV,ArrayList<ArrayList<int[]>>adj,intsrc,intdest){int[]dist=newint[V];Arrays.fill(dist,Integer.MAX_VALUE);PriorityQueue<int[]>pq=newPriorityQueue<>(Comparator.comparingInt(a->a[0]));dist[src]=0;pq.offer(newint[]{0,src});while(!pq.isEmpty()){int[]current=pq.poll();intd=current[0];intu=current[1];if(d>dist[u])continue;for(int[]neighbor:adj.get(u)){intv=neighbor[0];intw=neighbor[1];// direct edge being removed to check for a cycleif((u==src&&v==dest)||(u==dest&&v==src))continue;if(dist[v]>dist[u]+w){dist[v]=dist[u]+w;pq.offer(newint[]{dist[v],v});}}}returndist[dest];}// Function to find the minimum weight cycle in the graphpublicstaticintfindMinCycle(intV,int[][]edges){ArrayList<ArrayList<int[]>>adj=constructAdj(V,edges);intminCycle=Integer.MAX_VALUE;for(int[]edge:edges){intu=edge[0],v=edge[1],w=edge[2];intdist=shortestPath(V,adj,u,v);if(dist!=Integer.MAX_VALUE){minCycle=Math.min(minCycle,dist+w);}}returnminCycle;}//Driver Code Startspublicstaticvoidmain(String[]args){intV=5;// Graph edges represented as {u, v, weight}int[][]edges={{0,1,2},{1,2,2},{1,3,1},{1,4,1},{0,4,3},{2,3,4}};// Output the minimum weight cycleSystem.out.println(findMinCycle(V,edges));}}//Driver Code Ends
Python
#Driver Code Startsimportheapq# Construct adjacency list using list of listsdefconstructadj(V,edges):adj=[[]for_inrange(V)]foredgeinedges:u,v,w=edgeadj[u].append((v,w))adj[v].append((u,w))returnadj#Driver Code Ends# find shortest path from src to dest# while ignoring the edge between source and destinationdefshortestPath(V,adj,src,dest):# Initialize distance array with infinitydist=[float('inf')]*Vdist[src]=0# Priority queue to store (distance, vertex)pq=[(0,src)]whilepq:d,u=heapq.heappop(pq)# If we already found a better path, skip this oneifd>dist[u]:continue# Traverse neighborsforv,winadj[u]:# ignored edge from source and destinationif(u==srcandv==dest)or(u==destandv==src):continue# Relaxation stepifdist[v]>dist[u]+w:dist[v]=dist[u]+wheapq.heappush(pq,(dist[v],v))returndist[dest]# Function to find the minimum weight cycle in the graphdeffindMinCycle(V,edges):# Build the adjacency list onceadj=constructadj(V,edges)minCycle=float('inf')# Try removing each edge one by oneforedgeinedges:u,v,w=edgedist=shortestPath(V,adj,u,v)# If such a path exists, it forms a cycle with (u, v)ifdist!=float('inf'):minCycle=min(minCycle,dist+w)# If no cycle found, return -1returnminCycle#Driver Code Starts# Driver codeif__name__=="__main__":V=5# Graph edges represented as [u, v, weight]edges=[[0,1,2],[1,2,2],[1,3,1],[1,4,1],[0,4,3],[2,3,4]]print(findMinCycle(V,edges))#Driver Code Ends
C#
//Driver Code StartsusingSystem;usingSystem.Collections.Generic;classGfG{// Custom Min-Heap classMinHeap{privateList<(intdist,intnode)>heap=newList<(int,int)>();privatevoidSwap(inti,intj){vartemp=heap[i];heap[i]=heap[j];heap[j]=temp;}privatevoidHeapifyUp(inti){while(i>0){intparent=(i-1)/2;if(heap[i].dist>=heap[parent].dist)break;Swap(i,parent);i=parent;}}privatevoidHeapifyDown(inti){intn=heap.Count;while(true){intleft=2*i+1;intright=2*i+2;intsmallest=i;if(left<n&&heap[left].dist<heap[smallest].dist)smallest=left;if(right<n&&heap[right].dist<heap[smallest].dist)smallest=right;if(smallest==i)break;Swap(i,smallest);i=smallest;}}publicvoidPush(intdist,intnode){heap.Add((dist,node));HeapifyUp(heap.Count-1);}public(intdist,intnode)Pop(){if(heap.Count==0)thrownewInvalidOperationException("Heap is empty");varresult=heap[0];heap[0]=heap[heap.Count-1];heap.RemoveAt(heap.Count-1);HeapifyDown(0);returnresult;}publicboolIsEmpty(){returnheap.Count==0;}}// Construct adjacency liststaticList<List<int[]>>constructadj(intV,int[,]edges){varadj=newList<List<int[]>>();for(inti=0;i<V;i++)adj.Add(newList<int[]>());intE=edges.GetLength(0);for(inti=0;i<E;i++){intu=edges[i,0],v=edges[i,1],w=edges[i,2];adj[u].Add(newint[]{v,w});adj[v].Add(newint[]{u,w});}//Driver Code Endsreturnadj;}// find shortest path from src to dest// while ignoring the edge between source and destinationstaticintshortestPath(intV,List<List<int[]>>adj,intsrc,intdest){int[]dist=newint[V];for(inti=0;i<V;i++)dist[i]=int.MaxValue;varpq=newMinHeap();dist[src]=0;pq.Push(0,src);while(!pq.IsEmpty()){var(d,u)=pq.Pop();if(d>dist[u])continue;foreach(varedgeinadj[u]){intv=edge[0],w=edge[1];// Skip the direct edge from src to destif((u==src&&v==dest)||(u==dest&&v==src))continue;if(dist[v]>dist[u]+w){dist[v]=dist[u]+w;pq.Push(dist[v],v);}}}returndist[dest];}// Find the minimum cycle weightstaticintfindMinCycle(intV,int[,]edges){varadj=constructadj(V,edges);intminCycle=int.MaxValue;intE=edges.GetLength(0);for(inti=0;i<E;i++){intu=edges[i,0],v=edges[i,1],w=edges[i,2];intdist=shortestPath(V,adj,u,v);if(dist!=int.MaxValue){minCycle=Math.Min(minCycle,dist+w);}}returnminCycle;//Driver Code Starts}staticvoidMain(){intV=9;int[,]edges=newint[,]{{0,1,2},{1,2,2},{1,3,1},{1,4,1},{0,4,3},{2,3,4}};Console.WriteLine(findMinCycle(V,edges));}}//Driver Code Ends
JavaScript
//Driver Code Starts// Min-Heap based Priority QueueclassMinHeap{constructor(){this.heap=[];}push([dist,node]){this.heap.push([dist,node]);this._bubbleUp(this.heap.length-1);}pop(){constmin=this.heap[0];constend=this.heap.pop();if(this.heap.length>0){this.heap[0]=end;this._sinkDown(0);}returnmin;}_bubbleUp(index){constelement=this.heap[index];while(index>0){constparentIdx=Math.floor((index-1)/2);constparent=this.heap[parentIdx];if(element[0]>=parent[0])break;this.heap[index]=parent;this.heap[parentIdx]=element;index=parentIdx;}}_sinkDown(index){constlength=this.heap.length;constelement=this.heap[index];while(true){letleftIdx=2*index+1;letrightIdx=2*index+2;letswap=null;if(leftIdx<length){if(this.heap[leftIdx][0]<element[0]){swap=leftIdx;}}if(rightIdx<length){if((swap===null&&this.heap[rightIdx][0]<element[0])||(swap!==null&&this.heap[rightIdx][0]<this.heap[leftIdx][0])){swap=rightIdx;}}if(swap===null)break;this.heap[index]=this.heap[swap];this.heap[swap]=element;index=swap;}}isEmpty(){returnthis.heap.length===0;}}// Construct adjacency listfunctionconstructadj(V,edges){letadj=Array.from({length:V},()=>[]);for(let[u,v,w]ofedges){adj[u].push([v,w]);adj[v].push([u,w]);}returnadj;}//Driver Code Ends// find shortest path from src to dest// while ignoring the edge between source and destinationfunctionshortestPath(V,adj,src,dest){letdist=newArray(V).fill(Infinity);dist[src]=0;letpq=newMinHeap();pq.push([0,src]);while(!pq.isEmpty()){let[d,u]=pq.pop();if(d>dist[u])continue;for(let[v,w]ofadj[u]){// ignore direct connection between src and destif((u===src&&v===dest)||(u===dest&&v===src))continue;if(dist[v]>dist[u]+w){dist[v]=dist[u]+w;pq.push([dist[v],v]);}}}returndist[dest];}// Find minimum cycle in the graphfunctionfindMinCycle(V,edges){letadj=constructadj(V,edges);letminCycle=Infinity;for(let[u,v,w]ofedges){letdist=shortestPath(V,adj,u,v);if(dist!==Infinity){minCycle=Math.min(minCycle,dist+w);}}returnminCycle;}//Driver Code Starts// Driver codeletV=5;letedges=[[0,1,2],[1,2,2],[1,3,1],[1,4,1],[0,4,3],[2,3,4]];console.log(findMinCycle(V,edges));//Driver Code Ends
Output
6
Time Complexity: O(E * (V + E) log V) for iterating over each edge and running Dijkstra's algorithm, which involves creating a new adjacency list and recalculating shortest paths multiple times. Space Complexity: O(V + E) for the adjacency list, temporary edge storage, and Dijkstra's algorithm data structures like the distance array and priority queue.
We use cookies to ensure you have the best browsing experience on our website. By using our site, you
acknowledge that you have read and understood our
Cookie Policy &
Privacy Policy
Improvement
Suggest Changes
Help us improve. Share your suggestions to enhance the article. Contribute your expertise and make a difference in the GeeksforGeeks portal.
Create Improvement
Enhance the article with your expertise. Contribute to the GeeksforGeeks community and help create better learning resources for all.