Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Check for existence of Hamiltonian walk in O(2^n) of memory and O(2^n *n) of time

We can simply modify the travelling salesman problem to get whether a Hamilton walk exists or not in O(2^N * N^2)Time Complexity.

But I read it at codeforces that it is possible to solve this problem in O(2^N * N) Time .

Although , I cannot understand the state they are considering, but they are kind of compressing the original state of Travelling Salesman Problem.

Can someone give me a detailed explanation, I am new to bitmasking + DP (Infact I started today :D)

If you want you can look Point 4 at Codeforces

like image 532
Shubham Sharma Avatar asked Dec 31 '25 10:12

Shubham Sharma


1 Answers

Terminology:

  1. binary (x) means x is based 2.
  2. Nodes numbered starting from 0
  3. mask always represent a set of nodes. A node i is in mask means 2^i AND mask != 0. In the same way set mask-i (here - means removing i from the set) can be represented as mask XOR 2^i in bitmask.

Let mask be the bitmask of a set of nodes. We define dp[mask] as the bitmask of another set of nodes, which contains a node i if and only if:

  1. i in mask
  2. a hamilton walk exists for the set of nodes mask, which ends in node i

For example, dp[binary(1011)] = binary(1010) means that a hamilton walk exists for binary(1011) which ends in node 1, and another hamilton walk exists for binary(1011) which ends in node 3

So for N nodes, a hamilton walk exists for all of them if dp[2^N - 1] != 0

Then as described in the Codeforces link you posted, we can calculate dp[] by:

When mask only contains one node i

dp[2^i] = 2^i (which means for a single node, a walk always exists, and it ends at itself.

Otherwise

Given mask, by definition of dp[mask], for every node i in mask, we want to know if a walk exist for mask, and ends at i. To calculate this, we first check if any walk exists for the set of nodes mask-i, then check among those walks of mask-i, if there's a walk ends at a node j that's connected to i. Since combining them gives us a walk of mask that ends at i.

To make this step faster, we pre-process M[i] to be the bitmask of all notes connected to i. So i in dp[mask] if dp[mask XOR 2^i] AND M[i] != 0.

To explain a bit more about this step, dp[mask XOR 2^i] is the set of nodes that walk of mask-i can end, and M[i] is the set of nodes that's directly connected to i. So the AND of them means if any walk of mask that ends in i exists.

dp[] is O(2^N) in space. Calculating dp[] looks like

for mask = range(0, 2^N):
  for i in range(0,N):
    if 2^i AND mask != 0: # Node i in mask
      if (mask only has one node) || (dp[mask XOR 2^i] AND M[i] != 0):
        dp[mask] = dp[mask] OR 2^i # adding node i to dp[mask]

Which is O(2^N * N)

like image 74
lavin Avatar answered Jan 02 '26 09:01

lavin



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!