📜  计算给定有向图中的所有哈密顿路径

📅  最后修改于: 2022-05-13 01:57:52.989000             🧑  作者: Mango

计算给定有向图中的所有哈密顿路径

给定一个N个顶点的有向图,其值从0N – 1 ,大小为K的数组graph[]表示给定图的邻接表,任务是计算其中从第0顶点开始并结束的所有哈密顿路径在(N – 1)顶点。

注意:哈密顿路径定义为仅访问图的每个顶点一次的路径。

例子:

方法:给定问题可以通过使用带有动态规划的位掩码来解决,并迭代由N大小的掩码表示的给定顶点的所有子集,并检查是否存在从第0顶点开始并在(N – 1) th顶点并计算所有此类路径。假设对于具有N个顶点的图S表示一个位掩码,其中S = 0S = (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 个顶点的子集,并且必须有从ji的边。请按照以下步骤解决给定的问题:

  • 用 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]。
  • 执行上述步骤后,打印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)