Problem: Hamiltonian Cycle
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.
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".

Sample Input: N=5, 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]]
Sample Output: [0, 1, 2, 4, 3, 0]

Solution (cpp):
#include <iostream>
#include <vector>

using namespace std;

// Check if it's valid to place vertex at current position
bool isSafe(int vertex, vector<vector<int>> &adjMat, 
            vector<int> &path, int pos) {
    
    // The vertex must be adjacent to the previous vertex
    if (!adjMat[path[pos - 1]][vertex]) {
        return false;
    }

    // The vertex must not already be in the path
    for (int i = 0; i < pos; i++) {
        if (path[i] == vertex) {
            return false;
        }
    }

    return true;
}

// Recursive backtracking to construct Hamiltonian Cycle
bool hamCycleUtil(vector<vector<int>> &adjMat, 
                  vector<int> &path, int pos, int n) {
    
    // Base case: all vertices are in the path
    if (pos == n) {
        
        // Check if there's an edge from last to first vertex
        return adjMat[path[pos - 1]][path[0]];
    }

    // Try all possible vertices as next candidate
    for (int v = 1; v < n; v++) {
        if (isSafe(v, adjMat, path, pos)) {
            path[pos] = v;

            if (hamCycleUtil(adjMat, path, pos + 1, n)) {
                return true;
            }

            // Backtrack if v doesn't lead to a solution
            path[pos] = -1;
        }
    }

    return false;
}

// Initialize path and invoke backtracking function
vector<int> hamCycle(vector<vector<int>> &adjMat) {
    int n = adjMat.size();
    vector<int> path(n, -1);

    // Start path with vertex 0
    path[0] = 0;

    if (!hamCycleUtil(adjMat, path, 1, n)) {
        return {-1};
    }

    return path;
}

// Driver Code
int main() {
    
    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 (int i = 0; i < path.size(); i++) {
           cout << path[i] << " ";
        }
        cout << path[0];
    }
    return 0;
}