【问题标题】:why does floyd warshall just use one distance matrix?为什么弗洛伊德战争只使用一个距离矩阵?
【发布时间】:2015-08-30 10:43:09
【问题描述】:

我阅读了弗洛伊德 Warshall 算法的伪代码 1 let dist be a |V| × |V| array of minimum distances initialized to ∞ (infinity) 2 for each vertex v 3 dist[v][v] ← 0 4 for each edge (u,v) 5 dist[u][v] ← w(u,v) // the weight of the edge (u,v) 6 for k from 1 to |V| 7 for i from 1 to |V| 8 for j from 1 to |V| 9 if dist[i][j] > dist[i][k] + dist[k][j] 10 dist[i][j] ← dist[i][k] + dist[k][j] 11 end if 但它只是使用一个 dist 矩阵来节省距离。 我认为应该有 n 个 dist 矩阵,其中 n 是顶点数, 或者至少我们需要两个 dist 矩阵。 1 存储顶点 k-1 内的当前最短路径, 另一个存储顶点 k 内的最短路径, 然后第一个存储 k+1 内的最短路径, …… 对于顶点 k-1 内的距离,我们如何才能将顶点 k 内的新最短路径距离存储在原始矩阵中?

这张图显示我们需要 D0, D1, D2....D(n)

【问题讨论】:

  • 这是一个二维矩阵,其中 dist[i][j] 存储从节点 i 到节点 j 的距离。该算法的一大优点是它可以在原地工作。不需要额外的矩阵。仔细研究,你就会明白为什么......
  • 这对迭代进行编号以帮助数学证明正确性。这是一种常见的证明技术。这并不意味着需要 3d 矩阵。如果需要 3d 矩阵,则将 k 作为第三个下标。正如我所说,如果你仔细分析它,你就会明白为什么只需要一个矩阵。

标签: c++ c algorithm graph floyd-warshall


【解决方案1】:

你是对的,原始公式要求步骤k的计算需要使用步骤k-1的计算:

如您所说,如果第一个矩阵用于存储来自步骤k-1 的值,则可以轻松组织第二个矩阵用于存储来自k 的值,第一个矩阵再次用于存储来自k+1 的值等等。

但是,如果我们在更新值时使用相同的矩阵,在上面的公式中,如果索引 i,k 的值在当前轮 k 中已经更新,我们可能会不小心使用 而不是 ,或者如果索引k,j 的值已更新,我们可能会得到 而不是。这会不会违反算法,因为我们使用了错误的递归更新公式?

嗯,不是真的。请记住,Floyd-Warshall 算法处理“无负循环”约束,这意味着不存在边缘总和为负值的循环。这意味着对于任何k,从节点k 到节点k 的最短路径是0(否则这意味着从kk 的路径总和为负价值)。所以根据定义:

现在,我们只取第一个公式,将j 替换为k

然后让我们将同一个公式中的“i”替换为“k”:

所以,基本上, 将具有与 相同的值, 将具有与 相同的值,因此这些值是否在循环期间更新并不重要'k' ,因此您可以在读取时更新相同的矩阵而不会破坏算法。

【讨论】:

    【解决方案2】:

    您在这里部分正确。

    Floyd Warshall 算法的输出(即 NxN 矩阵)无助于重建任意两个给定顶点之间的实际最短路径。

    如果我们保留一个父矩阵 P,这些路径可以恢复,这样它就可以存储用于每个顶点对 (x, y) 的最后一个中间顶点。假设这个值为 k。

    x 到 y 的最短路径是 x 到 k 的最短路径与 k 到 y 的最短路径的串联,可以在给定矩阵 P 的情况下递归重构。

    但是,请注意,大多数全对应用程序只需要生成的距离矩阵。这些工作正是 Floyd 算法的设计目的。

    【讨论】:

    • 我不认为这回答了这个问题,因为它没有询问重建最短路径,而是询问同一矩阵如何同时用于读取和写入(如果我理解正确)
    猜你喜欢
    • 1970-01-01
    • 2018-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-17
    • 2011-04-22
    • 1970-01-01
    • 2013-03-28
    相关资源
    最近更新 更多