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 (python):
# Check if it's valid to place vertex at current position
def isSafe(vertex, adjMat, path, pos):

    # The vertex must be adjacent to the previous vertex
    if adjMat[path[pos - 1]][vertex] == 0:
        return False

    # The vertex must not already be in the path
    for i in range(pos):
        if path[i] == vertex:
            return False

    return True


# Recursive backtracking to construct Hamiltonian Cycle
def hamCycleUtil(adjMat, path, pos, 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]] == 1

    # Try all possible vertices as next candidate
    for v in range(1, n):
        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
def hamCycle(adjMat):

    n = len(adjMat)
    path = [-1] * n

    # Start path with vertex 0
    path[0] = 0

    if not hamCycleUtil(adjMat, path, 1, n):
        return [-1]

    return path


if __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)
    
    if path[0] == -1:
        print("Solution does not Exist")
    else:
        for v in path:
            print(v, end=" ")
        print(path[0])