Related Articles
Hamiltonian Path ( Using Dynamic Programming )
• Difficulty Level : Easy
• Last Updated : 31 May, 2021

Given an adjacency matrix adj[][] of an undirected graph consisting of N vertices, the task is to find whether the graph contains a Hamiltonian Path or not. If found to be true, then print “Yes”. Otherwise, print “No”.

A Hamiltonian path is defined as the path in a directed or undirected graph which visits each and every vertex of the graph exactly once.

Examples:

Input: adj[][] = {{0, 1, 1, 1, 0}, {1, 0, 1, 0, 1}, {1, 1, 0, 1, 1}, {1, 0, 1, 0, 0}}
Output: Yes
Explanation:
There exists a Hamiltonian Path for the given graph as shown in the image below:

Input: adj[][] = {{0, 1, 0, 0}, {1, 0, 1, 1}, {0, 1, 0, 0}, {0, 1, 0, 0}}
Output: No

Naive Approach: The simplest approach to solve the given problem is to generate all the possible permutations of N vertices. For each permutation, check if it is a valid Hamiltonian path by checking if there is an edge between adjacent vertices or not. If found to be true, then print “Yes”. Otherwise, print “No”.

Time Complexity: O(N * N!)
Auxiliary Space: O(1)

Efficient Approach: The above approach can be optimized by using Dynamic Programming and Bit Masking which is based on the following observations:

• The idea is such that for every subset S of vertices, check whether there is a hamiltonian path in the subset S that ends at vertex v where v â‚¬ S.
• If v has a neighbor u, where u â‚¬ S – {v}, therefore, there exists a Hamiltonian path that ends at vertex u.
• The problem can be solved by generalizing the subset of vertices and the ending vertex of the Hamiltonian path.

Follow the steps below to solve the problem:

• Initialize a boolean matrix dp[][] in dimension N*2N where dp[j ][i] represents whether there exists a path in the subset or not represented by the mask i that visits each and every vertex in i once and ends at vertex j.
• For the base case, update dp[i][1 << i] = true, for i in range [0, N – 1]
• Iterate over the range [1, 2N – 1] using the variable i and perform the following steps:
• All the vertices with bits set in mask i, are included in the subset.
• Iterate over the range [1, N] using the variable j that will represent the end vertex of the hamiltonian path of current subset mask i and perform the following steps:
• Iterate over the range using the variable i and if the value of dp[i][2N – 1] is true, then there exists a hamiltonian path ending at vertex i. Therefore, print “Yes”. Otherwise, print “No”.

Below is the implementation of the above approach:

## C++

 `// C++ program for the above approach`   `#include ` `using` `namespace` `std;` `const` `int` `N = 5;`   `// Function to check whether there` `// exists a Hamiltonian Path or not` `bool` `Hamiltonian_path(` `    ``vector >& adj, ``int` `N)` `{` `    ``int` `dp[N][(1 << N)];`   `    ``// Initialize the table` `    ``memset``(dp, 0, ``sizeof` `dp);`   `    ``// Set all dp[i][(1 << i)] to` `    ``// true` `    ``for` `(``int` `i = 0; i < N; i++)` `        ``dp[i][(1 << i)] = ``true``;`   `    ``// Iterate over each subset` `    ``// of nodes` `    ``for` `(``int` `i = 0; i < (1 << N); i++) {`   `        ``for` `(``int` `j = 0; j < N; j++) {`   `            ``// If the jth nodes is included` `            ``// in the current subset` `            ``if` `(i & (1 << j)) {`   `                ``// Find K, neighbour of j` `                ``// also present in the` `                ``// current subset` `                ``for` `(``int` `k = 0; k < N; k++) {`   `                    ``if` `(i & (1 << k)` `                        ``&& adj[k][j]` `                        ``&& j != k` `                        ``&& dp[k][i ^ (1 << j)]) {`   `                        ``// Update dp[j][i]` `                        ``// to true` `                        ``dp[j][i] = ``true``;` `                        ``break``;` `                    ``}` `                ``}` `            ``}` `        ``}` `    ``}`   `    ``// Traverse the vertices` `    ``for` `(``int` `i = 0; i < N; i++) {`   `        ``// Hamiltonian Path exists` `        ``if` `(dp[i][(1 << N) - 1])` `            ``return` `true``;` `    ``}`   `    ``// Otherwise, return false` `    ``return` `false``;` `}`   `// Driver Code` `int` `main()` `{`   `    ``// Input` `    ``vector > adj = { { 0, 1, 1, 1, 0 },` `                                 ``{ 1, 0, 1, 0, 1 },` `                                 ``{ 1, 1, 0, 1, 1 },` `                                 ``{ 1, 0, 1, 0, 0 } };` `    ``int` `N = adj.size();`   `    ``// Function Call` `    ``if` `(Hamiltonian_path(adj, N))` `        ``cout << ``"YES"``;` `    ``else` `        ``cout << ``"NO"``;`   `    ``return` `0;` `}`

## Java

 `// Java program for the above approach` `import` `java.io.*;` `import` `java.lang.*;` `import` `java.util.*;`   `class` `GFG{`   `// Function to check whether there` `// exists a Hamiltonian Path or not` `static` `boolean` `Hamiltonian_path(``int` `adj[][], ``int` `N)` `{` `    ``boolean` `dp[][] = ``new` `boolean``[N][(``1` `<< N)];`   `    ``// Set all dp[i][(1 << i)] to` `    ``// true` `    ``for``(``int` `i = ``0``; i < N; i++)` `        ``dp[i][(``1` `<< i)] = ``true``;`   `    ``// Iterate over each subset` `    ``// of nodes` `    ``for``(``int` `i = ``0``; i < (``1` `<< N); i++) ` `    ``{` `        ``for``(``int` `j = ``0``; j < N; j++) ` `        ``{` `            `  `            ``// If the jth nodes is included` `            ``// in the current subset` `            ``if` `((i & (``1` `<< j)) != ``0``)` `            ``{`   `                ``// Find K, neighbour of j` `                ``// also present in the` `                ``// current subset` `                ``for``(``int` `k = ``0``; k < N; k++) ` `                ``{` `                    `  `                    ``if` `((i & (``1` `<< k)) != ``0` `&& ` `                         ``adj[k][j] == ``1` `&& j != k && ` `                           ``dp[k][i ^ (``1` `<< j)])` `                    ``{` `                        `  `                        ``// Update dp[j][i]` `                        ``// to true` `                        ``dp[j][i] = ``true``;` `                        ``break``;` `                    ``}` `                ``}` `            ``}` `        ``}` `    ``}`   `    ``// Traverse the vertices` `    ``for``(``int` `i = ``0``; i < N; i++) ` `    ``{` `        `  `        ``// Hamiltonian Path exists` `        ``if` `(dp[i][(``1` `<< N) - ``1``])` `            ``return` `true``;` `    ``}`   `    ``// Otherwise, return false` `    ``return` `false``;` `}`   `// Driver Code` `public` `static` `void` `main(String[] args)` `{` `    ``int` `adj[][] = { { ``0``, ``1``, ``1``, ``1``, ``0` `},` `                    ``{ ``1``, ``0``, ``1``, ``0``, ``1` `},` `                    ``{ ``1``, ``1``, ``0``, ``1``, ``1` `},` `                    ``{ ``1``, ``0``, ``1``, ``0``, ``0` `} };` `    ``int` `N = adj.length;`   `    ``// Function Call` `    ``if` `(Hamiltonian_path(adj, N))` `        ``System.out.println(``"YES"``);` `    ``else` `        ``System.out.println(``"NO"``);` `}` `}`   `// This code is contributed by Kingash`

## Python3

 `# Python3 program for the above approach`   `# Function to check whether there` `# exists a Hamiltonian Path or not` `def` `Hamiltonian_path(adj, N):` `    `  `    ``dp ``=` `[[``False` `for` `i ``in` `range``(``1` `<< N)] ` `                 ``for` `j ``in` `range``(N)]`   `    ``# Set all dp[i][(1 << i)] to` `    ``# true` `    ``for` `i ``in` `range``(N):` `        ``dp[i][``1` `<< i] ``=` `True`   `    ``# Iterate over each subset` `    ``# of nodes` `    ``for` `i ``in` `range``(``1` `<< N):` `        ``for` `j ``in` `range``(N):`   `            ``# If the jth nodes is included` `            ``# in the current subset` `            ``if` `((i & (``1` `<< j)) !``=` `0``):`   `                ``# Find K, neighbour of j` `                ``# also present in the` `                ``# current subset` `                ``for` `k ``in` `range``(N):` `                    ``if` `((i & (``1` `<< k)) !``=` `0` `and` `                             ``adj[k][j] ``=``=` `1` `and` `                                     ``j !``=` `k ``and` `                          ``dp[k][i ^ (``1` `<< j)]):` `                        `  `                        ``# Update dp[j][i]` `                        ``# to true` `                        ``dp[j][i] ``=` `True` `                        ``break` `    `  `    ``# Traverse the vertices` `    ``for` `i ``in` `range``(N):`   `        ``# Hamiltonian Path exists` `        ``if` `(dp[i][(``1` `<< N) ``-` `1``]):` `            ``return` `True`   `    ``# Otherwise, return false` `    ``return` `False`   `# Driver Code` `adj ``=` `[ [ ``0``, ``1``, ``1``, ``1``, ``0` `] ,` `        ``[ ``1``, ``0``, ``1``, ``0``, ``1` `],` `        ``[ ``1``, ``1``, ``0``, ``1``, ``1` `],` `        ``[ ``1``, ``0``, ``1``, ``0``, ``0` `] ]`   `N ``=` `len``(adj)`   `if` `(Hamiltonian_path(adj, N)):` `    ``print``(``"YES"``)` `else``:` `    ``print``(``"NO"``)`   `# This code is contributed by maheshwaripiyush9`

## C#

 `// C# program for the above approach` `using` `System;`   `class` `GFG{`   `// Function to check whether there` `// exists a Hamiltonian Path or not` `static` `bool` `Hamiltonian_path(``int``[,] adj, ``int` `N)` `{` `    ``bool``[,] dp = ``new` `bool``[N, (1 << N)];`   `    ``// Set all dp[i][(1 << i)] to` `    ``// true` `    ``for``(``int` `i = 0; i < N; i++)` `        ``dp[i, (1 << i)] = ``true``;`   `    ``// Iterate over each subset` `    ``// of nodes` `    ``for``(``int` `i = 0; i < (1 << N); i++)` `    ``{` `        ``for``(``int` `j = 0; j < N; j++)` `        ``{` `            `  `            ``// If the jth nodes is included` `            ``// in the current subset` `            ``if` `((i & (1 << j)) != 0) ` `            ``{` `                `  `                ``// Find K, neighbour of j` `                ``// also present in the` `                ``// current subset` `                ``for``(``int` `k = 0; k < N; k++)` `                ``{` `                    `  `                    ``if` `((i & (1 << k)) != 0 && ` `                        ``adj[k, j] == 1 && j != k && ` `                        ``dp[k, i ^ (1 << j)]) ` `                    ``{`   `                        ``// Update dp[j][i]` `                        ``// to true` `                        ``dp[j, i] = ``true``;` `                        ``break``;` `                    ``}` `                ``}` `            ``}` `        ``}` `    ``}`   `    ``// Traverse the vertices` `    ``for``(``int` `i = 0; i < N; i++) ` `    ``{` `        `  `        ``// Hamiltonian Path exists` `        ``if` `(dp[i, (1 << N) - 1])` `            ``return` `true``;` `    ``}`   `    ``// Otherwise, return false` `    ``return` `false``;` `}`   `// Driver Code` `public` `static` `void` `Main(String[] args)` `{` `    ``int``[,] adj = { { 0, 1, 1, 1, 0 },` `                   ``{ 1, 0, 1, 0, 1 },` `                   ``{ 1, 1, 0, 1, 1 },` `                   ``{ 1, 0, 1, 0, 0 } };` `    ``int` `N = adj.GetLength(0);`   `    ``// Function Call` `    ``if` `(Hamiltonian_path(adj, N))` `        ``Console.WriteLine(``"YES"``);` `    ``else` `        ``Console.WriteLine(``"NO"``);` `}` `}`   `// This code is contributed by ukasp`

## Javascript

 ``

Output:

`YES`

Time Complexity: O(N * 2N)
Auxiliary Space: O(N * 2N)

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.  To complete your preparation from learning a language to DS Algo and many more,  please refer Complete Interview Preparation Course.

In case you wish to attend live classes with industry experts, please refer DSA Live Classes

My Personal Notes arrow_drop_up
Recommended Articles
Page :