图形遍历n步

时间:2012-04-27 06:54:26

标签: c++ c algorithm graph

给出一个像这样的简单无向图:

enter image description here

从D,A,B或C(V_start)开始 - 我必须计算从起点(V_start)到起点({{1})的可能路径数量} V_start步骤,其中每个边和顶点可以无限次访问。

我正在考虑进行深度优先搜索,在n时停止,但是,如果steps > n || (steps == n && vertex != V_start),这会变得相当昂贵。我的下一个想法让我将DFS与动态编程相结合,然而,这就是我被困住的地方。

(这不是家庭作业,只是为了学习而被困在图表和算法中。)

如何在合理的时间内使用大n = 1000000来解决这个问题?

2 个答案:

答案 0 :(得分:20)

此任务通过矩阵乘法求解。

如果存在从nn的路径,则创建包含0和1的矩阵mat[i][j] x i(对于单元格j为1)。将此矩阵乘以k次(考虑使用快速矩阵求幂)。然后在矩阵的单元格mat[i][j]中,您拥有从k开始到i结尾的长度为j的路径数。

注意:快速矩阵取幂基本上与快速取幂相同,只是你将数乘以矩阵乘以数字。

注2:让我们假设n是图中的顶点数。然后我在这里提出的算法在时间复杂度O(log k * n 3 )中运行,并且具有O(n 2 )的存储器复杂度。如果您使用here所述的优化矩阵乘法,您可以进一步改进它。然后时间复杂度将变为O(log k * n log 2 7 )。


编辑根据Antoine的要求,我解释了为什么这个算法真正起作用的解释:

我将通过归纳证明该算法。归纳的基础是显而易见的:最初我在矩阵中有长度为1的路径数。

我们假设,如果我将矩阵提升到k的幂,k的幂,我在mat[i][j]中的长度为k的路径数量为i jk + 1

现在让我们考虑下一步k + 1。很明显,每个长度为k的路径都包含长度为k + 1的前缀和一条边。这基本上意味着长度mat_pow_k的路径可以通过(这里我用k表示提升到n幂的矩阵来计算

num_paths(x,y,k + 1)= sum i = 0 i< n mat_pow_k [x] [i] * mat [i] [y]

再次:mat[i][y]是图中顶点的数量。这可能需要一段时间才能理解,但基本上只有在xy之间存在直接边缘时,初始矩阵在其k + 1单元格中才有1。我们会计算此边缘的所有可能前缀,以形成长度为k + 1的路径。

然而,我写的最后一件事实际上是在计算mat {{1}}的强大功能,这证明了归纳的步骤和我的陈述。

答案 1 :(得分:2)

这非常像动态编程问题:

  1. 将f [n] [m]定义为以m步开始从起点到点n的路径数
  2. 从每个点n到其相邻的k,你有公式:f [k] [m + 1] = f [k] [m + 1] + f [n] [m]
  3. 在初始化时,所有f [n] [m]都为0,但f [starting_point] [0] = 1
  4. 因此您可以计算最终结果
  5. 伪代码:

    memset(f, 0, sizeof(f));
    f[starting_point][0] = 1;
    for (int step = 0; step < n; ++step) {
        for (int point = 0; point < point_num; ++point) {
            for (int next_point = 0; next_point < point_num; ++ next_point) {
                if (adjacent[point][next_point]) {
                    f[next_point][step+1] += f[point][step];
                }
            }
        }
    }
    return f[starting_point][n]