计算给定有向图中的所有哈密顿路径
给定一个N个顶点的有向图,其值从0到N – 1 ,大小为K的数组graph[]表示给定图的邻接表,任务是计算其中从第0个顶点开始并结束的所有哈密顿路径在(N – 1)个顶点。
注意:哈密顿路径定义为仅访问图的每个顶点一次的路径。
例子:
Input: N = 4, K = 6, graph[][] = {{1, 2}, {1, 3}, {2, 3}, {3, 2}, {2, 4}, {3, 4}}
Output: 2
Explanation:
The paths below shown are 1 -> 3 -> 2 -> 4 and 1 -> 2 -> 3 -> 4 starts at 1 and ends at 4 and are called Hamiltonian paths.
Input: N = 2, K = 1, graph[][] = {{1, 2}}
Output: 1
方法:给定问题可以通过使用带有动态规划的位掩码来解决,并迭代由N大小的掩码表示的给定顶点的所有子集,并检查是否存在从第0个顶点开始并在(N – 1) th顶点并计算所有此类路径。假设对于具有N个顶点的图S表示一个位掩码,其中S = 0到S = (1 << N) -1并且dp[i][S]表示访问掩码S中每个顶点并结束的路径数在i处,有效的重复将被给出为dp[i][S] = ∑ dp[j][S XOR 2 i ] 其中 j ∈ S 并且从 j 到 i 有一条边,其中S XOR 2 i 表示其中没有第 i 个顶点的子集,并且必须有从j到i的边。请按照以下步骤解决给定的问题:
- 用 0 初始化一个二维数组dp[N][2 N ]并将 dp[ 0 ][1]设置为1 。
- 使用变量i遍历[2, 2 N – 1]的范围,并检查其中设置了所有位的掩码。
- 使用变量end遍历从[0, N)开始的范围,并遍历当前掩码的所有位,并将每个位假定为结束位。
- 将变量prev初始化为i – (1 << end)。
- 使用变量it遍历[0, size)范围,其中size是数组graph[end]的大小,并遍历当前结束位的相邻顶点并像这样更新dp[][]数组dp[end ][i] += dp[it][prev]。
- 使用变量end遍历从[0, N)开始的范围,并遍历当前掩码的所有位,并将每个位假定为结束位。
- 执行上述步骤后,打印dp[N-1][2 N – 1]的值作为答案。
下面是上述方法的实现:
C++
// C++ program for the above approach
#include
using namespace std;
// Function to find all possible paths
void findAllPaths(
int N, vector >& graph)
{
// Initialize a dp array
int dp[N][(1 << N)];
// Initialize it with 0
memset(dp, 0, sizeof dp);
// Initialize for the first vertex
dp[0][1] = 1;
// Iterate over all the masks
for (int i = 2; i < (1 << N); i++) {
// If the first vertex is absent
if ((i & (1 << 0)) == 0)
continue;
// Only consider the full subsets
if ((i & (1 << (N - 1)))
&& i != ((1 << N) - 1))
continue;
// Choose the end city
for (int end = 0; end < N; end++) {
// If this city is not in the subset
if (i & (1 << end) == 0)
continue;
// Set without the end city
int prev = i - (1 << end);
// Check for the adjacent cities
for (int it : graph[end]) {
if ((i & (1 << it))) {
dp[end][i] += dp[it][prev];
}
}
}
}
// Print the answer
cout << dp[N - 1][(1 << N) - 1];
}
// Driver Code
int main()
{
int N = 4;
vector > graph(N);
graph[1].push_back(0);
graph[2].push_back(0);
graph[2].push_back(1);
graph[1].push_back(2);
graph[3].push_back(1);
graph[3].push_back(2);
findAllPaths(N, graph);
return 0;
}
Python3
# python program for the above approach
# Function to find all possible paths
def findAllPaths(N, graph):
# Initialize a dp array
# Initialize it with 0
dp = [[0 for _ in range(1 << N)] for _ in range(N)]
# Initialize for the first vertex
dp[0][1] = 1
# Iterate over all the masks
for i in range(2, (1 << N)):
# If the first vertex is absent
if ((i & (1 << 0)) == 0):
continue
# Only consider the full subsets
if ((i & (1 << (N - 1)))and i != ((1 << N) - 1)):
continue
# Choose the end city
for end in range(0, N):
# If this city is not in the subset
if (i & (1 << end) == 0):
continue
# Set without the end city
prev = i - (1 << end)
# Check for the adjacent cities
for it in graph[end]:
if ((i & (1 << it))):
dp[end][i] += dp[it][prev]
# Print the answer
print(dp[N - 1][(1 << N) - 1])
# Driver Code
if __name__ == "__main__":
N = 4
graph = [[] for _ in range(N)]
graph[1].append(0)
graph[2].append(0)
graph[2].append(1)
graph[1].append(2)
graph[3].append(1)
graph[3].append(2)
findAllPaths(N, graph)
# This code is contributed by rakeshsahni
Javascript
2
时间复杂度: O(N*2 N )
辅助空间: O(1)