A Hamiltonian Cycle or Circuit in a graph G is a cycle that visits each vertex of G exactly once and returns to the starting vertex.
If a graph has a Hamiltonian cycle, it's a Hamiltonian graph; otherwise, it's non-Hamiltonian.
Finding a Hamiltonian cycle is an NP-complete problem, meaning there's no known efficient solution for all graph types, but solutions exist for smaller or specific types.
The Hamiltonian Cycle problem has applications in logistics, network design, and computer science.
Sample Problem
Given an undirected graph, the task is to determine if it contains a Hamiltonian cycle. If found, print the path; otherwise, print "Solution does not exist".
Generate all possible vertex configurations and print a configuration that satisfies the given constraints. This results in n! (n factorial) configurations. Therefore, the overall time complexity of this approach is at least O(n!).
[Expected Approach] Using Backtracking
Backtracking is used to find a Hamiltonian Cycle. Initialize an empty path array, place the starting vertex (e.g., 0) in the first position. Recursively add remaining vertices one by one, ensuring each new vertex is adjacent to the previous one and not already in the path. If a valid vertex is found, proceed; otherwise, backtrack.
Exemplification
Let's find out the Hamiltonian cycle for the following graph:
Start with node 0. Apply DFS to find a Hamiltonian path.
When all 'n' vertices are traversed, check if the current node is a neighbor of the starting node.
Since node 2 is not a neighbor of 0, return. As no cycle is found in path {0, 3, 1, 4, 2}, return from nodes 2 and 4.
Explore node 2. Check for a Hamiltonian cycle. Since node 4 is not a neighbor of 0, return. Return from nodes 4, 2, and 1.
Explore node 3. In path {0, 3, 4, 2, 1, 0}, a cycle is found, print this cyclic path. This is our Hamiltonian cycle.
Note: The algorithm currently starts from a fixed vertex, but a Hamiltonian cycle allows any vertex. Minor adjustments are needed to enable cycle initiation from any node.
C++
#include<iostream>#include<vector>usingnamespacestd;// Check if it's valid to place vertex at current positionboolisSafe(intvertex,vector<vector<int>>&adjMat,vector<int>&path,intpos){// The vertex must be adjacent to the previous vertexif(!adjMat[path[pos-1]][vertex]){returnfalse;}// The vertex must not already be in the pathfor(inti=0;i<pos;i++){if(path[i]==vertex){returnfalse;}}returntrue;}// Recursive backtracking to construct Hamiltonian CycleboolhamCycleUtil(vector<vector<int>>&adjMat,vector<int>&path,intpos,intn){// Base case: all vertices are in the pathif(pos==n){// Check if there's an edge from last to first vertexreturnadjMat[path[pos-1]][path[0]];}// Try all possible vertices as next candidatefor(intv=1;v<n;v++){if(isSafe(v,adjMat,path,pos)){path[pos]=v;if(hamCycleUtil(adjMat,path,pos+1,n)){returntrue;}// Backtrack if v doesn't lead to a solutionpath[pos]=-1;}}returnfalse;}// Initialize path and invoke backtracking functionvector<int>hamCycle(vector<vector<int>>&adjMat){intn=adjMat.size();vector<int>path(n,-1);// Start path with vertex 0path[0]=0;if(!hamCycleUtil(adjMat,path,1,n)){return{-1};}returnpath;}// Driver Codeintmain(){vector<vector<int>>adjMat={{0,1,0,1,0},{1,0,1,1,1},{0,1,0,0,1},{1,1,0,0,1},{0,1,1,1,0}};vector<int>path=hamCycle(adjMat);if(path[0]==-1){cout<<"Solution does not Exist";}else{for(inti=0;i<path.size();i++){cout<<path[i]<<" ";}cout<<path[0];}return0;}
Java
importjava.util.ArrayList;importjava.util.List;publicclassGFG{// Check if it's valid to place vertex at current positionprivatestaticbooleanisSafe(intvertex,int[][]adjMat,List<Integer>path,intpos){// The vertex must be adjacent to the previous vertexif(adjMat[path.get(pos-1)][vertex]==0){returnfalse;}// The vertex must not already be in the pathfor(inti=0;i<pos;i++){if(path.get(i)==vertex){returnfalse;}}returntrue;}// Recursive backtracking to construct Hamiltonian CycleprivatestaticbooleanhamCycleUtil(int[][]adjMat,List<Integer>path,intpos,intn){// Base case: all vertices are in the pathif(pos==n){// Check if there's an edge from last to first vertexreturnadjMat[path.get(pos-1)][path.get(0)]==1;}// Try all possible vertices as next candidatefor(intv=1;v<n;v++){if(isSafe(v,adjMat,path,pos)){path.set(pos,v);if(hamCycleUtil(adjMat,path,pos+1,n)){returntrue;}// Backtrack if v doesn't lead to a solutionpath.set(pos,-1);}}returnfalse;}// Initialize path and invoke backtracking functionpublicstaticList<Integer>hamCycle(int[][]adjMat){intn=adjMat.length;List<Integer>path=newArrayList<>(n);for(inti=0;i<n;i++){path.add(-1);}// Start path with vertex 0path.set(0,0);if(!hamCycleUtil(adjMat,path,1,n)){List<Integer>noSolution=newArrayList<>();noSolution.add(-1);returnnoSolution;}returnpath;}// Driver Codepublicstaticvoidmain(String[]args){int[][]adjMat={{0,1,0,1,0},{1,0,1,1,1},{0,1,0,0,1},{1,1,0,0,1},{0,1,1,1,0}};List<Integer>path=hamCycle(adjMat);if(path.get(0)==-1){System.out.println("Solution does not Exist");}else{for(inti=0;i<path.size();i++){System.out.print(path.get(i)+" ");}System.out.print(path.get(0));}}}
Python
# Check if it's valid to place vertex at current positiondefisSafe(vertex,adjMat,path,pos):# The vertex must be adjacent to the previous vertexifadjMat[path[pos-1]][vertex]==0:returnFalse# The vertex must not already be in the pathforiinrange(pos):ifpath[i]==vertex:returnFalsereturnTrue# Recursive backtracking to construct Hamiltonian CycledefhamCycleUtil(adjMat,path,pos,n):# Base case: all vertices are in the pathifpos==n:# Check if there's an edge from last to first vertexreturnadjMat[path[pos-1]][path[0]]==1# Try all possible vertices as next candidateforvinrange(1,n):ifisSafe(v,adjMat,path,pos):path[pos]=vifhamCycleUtil(adjMat,path,pos+1,n):returnTrue# Backtrack if v doesn't lead to a solutionpath[pos]=-1returnFalse# Initialize path and invoke backtracking functiondefhamCycle(adjMat):n=len(adjMat)path=[-1]*n# Start path with vertex 0path[0]=0ifnothamCycleUtil(adjMat,path,1,n):return[-1]returnpathif__name__=="__main__":adjMat=[[0,1,0,1,0],[1,0,1,1,1],[0,1,0,0,1],[1,1,0,0,1],[0,1,1,1,0]]path=hamCycle(adjMat)ifpath[0]==-1:print("Solution does not Exist")else:forvinpath:print(v,end=" ")print(path[0])
C#
usingSystem;usingSystem.Collections.Generic;classGFG{// Check if it's valid to place vertex at current positionstaticboolisSafe(intvertex,int[,]adjMat,List<int>path,intpos){// The vertex must be adjacent to the previous vertexif(adjMat[path[pos-1],vertex]==0){returnfalse;}// The vertex must not already be in the pathfor(inti=0;i<pos;i++){if(path[i]==vertex){returnfalse;}}returntrue;}// Recursive backtracking to construct Hamiltonian CyclestaticboolhamCycleUtil(int[,]adjMat,List<int>path,intpos,intn){// Base case: all vertices are in the pathif(pos==n){// Check if there's an edge from last to first vertexreturnadjMat[path[pos-1],path[0]]==1;}// Try all possible vertices as next candidatefor(intv=1;v<n;v++){if(isSafe(v,adjMat,path,pos)){path[pos]=v;if(hamCycleUtil(adjMat,path,pos+1,n)){returntrue;}// Backtrack if v doesn't lead to a solutionpath[pos]=-1;}}returnfalse;}// Initialize path and invoke backtracking functionstaticList<int>hamCycle(int[,]adjMat){intn=adjMat.GetLength(0);List<int>path=newList<int>();for(inti=0;i<n;i++)path.Add(-1);// Start path with vertex 0path[0]=0;if(!hamCycleUtil(adjMat,path,1,n)){returnnewList<int>{-1};}returnpath;}// Driver CodestaticvoidMain(){int[,]adjMat={{0,1,0,1,0},{1,0,1,1,1},{0,1,0,0,1},{1,1,0,0,1},{0,1,1,1,0}};List<int>path=hamCycle(adjMat);if(path[0]==-1){Console.WriteLine("Solution does not Exist");}else{foreach(intvinpath)Console.Write(v+" ");Console.Write(path[0]);}}}
JavaScript
// Check if it's valid to place vertex at current positionfunctionisSafe(vertex,adjMat,path,pos){// The vertex must be adjacent to the previous vertexif(adjMat[path[pos-1]][vertex]===0){returnfalse;}// The vertex must not already be in the pathfor(leti=0;i<pos;i++){if(path[i]===vertex){returnfalse;}}returntrue;}// Recursive backtracking to construct Hamiltonian CyclefunctionhamCycleUtil(adjMat,path,pos,n){// Base case: all vertices are in the pathif(pos===n){// Check if there's an edge from last to first vertexreturnadjMat[path[pos-1]][path[0]]===1;}// Try all possible vertices as next candidatefor(letv=1;v<n;v++){if(isSafe(v,adjMat,path,pos)){path[pos]=v;if(hamCycleUtil(adjMat,path,pos+1,n)){returntrue;}// Backtrack if v doesn't lead to a solutionpath[pos]=-1;}}returnfalse;}// Initialize path and invoke backtracking functionfunctionhamCycle(adjMat){constn=adjMat.length;constpath=newArray(n).fill(-1);// Start path with vertex 0path[0]=0;if(!hamCycleUtil(adjMat,path,1,n)){return[-1];}returnpath;}// Driver CodeconstadjMat=[[0,1,0,1,0],[1,0,1,1,1],[0,1,0,0,1],[1,1,0,0,1],[0,1,1,1,0]];constpath=hamCycle(adjMat);if(path[0]===-1){console.log("Solution does not Exist");}else{console.log(path.join(" ")+" "+path[0]);}