使用 Floyd-Warshall 查找所有最短路径和距离

Posted

技术标签:

【中文标题】使用 Floyd-Warshall 查找所有最短路径和距离【英文标题】:Finding all shortest paths and distances using Floyd-Warshall 【发布时间】:2011-04-30 10:48:12 【问题描述】:

首先,介绍一点背景知识:我正在使用基本图形算法(Dijkstra、Floyd-Warshall、Bellman-Ford 等)构建一个简单的图形类,以用作即将举行的编程竞赛的参考表。

到目前为止,我有一个 Floyd-Warshall 的功能版本,但缺点是到目前为止它只能让我获得两个节点之间的最短 距离值,而不是 最短路径时间>。最好我希望在算法本身内进行路径构建,而不必调用另一个函数来重建它。

以下是我正在使用的数据结构的一些信息:

vector< vector<int> > graph //contains the distance values from each node to each other node (graph[1][3] contains the length of the edge from node #1 to node #3, if no edge, the value is INF

vector< vector<int> > path //contains the "stepping stones" on how to reach a given node. path[st_node][end_node] contains the value of the next node on the way from end_node -> st_node

这是我正在使用的示例图表数据:

INF 10  INF INF INF INF
INF INF 90  15  INF INF
INF INF INF INF INF 20
INF INF INF INF 20  INF
INF INF  5  INF INF INF
INF INF INF INF INF INF

这是“路径”变量中的所需值(通过从每个节点运行 Dijkstra 获得):

INF  0   4   1   3   2
INF INF  4   1   3   2
INF INF INF INF INF  2
INF INF  4  INF  3   2
INF INF  4  INF INF  2
INF INF INF INF INF INF

这是我目前用于算法的代码的链接:(via PasteBin)。

任何帮助将不胜感激!

编辑:我尝试Wikipedia's code 生成路径矩阵,结果如下:

INF INF  4   1   3   4
INF INF  4  INF  3   4
INF INF INF INF INF INF
INF INF  4  INF INF  4
INF INF INF INF INF  2
INF INF INF INF INF INF

它有点工作,但在表示“单个”步骤时存在问题。例如,从节点 0 到节点 1 的路径在任何地方都是未定义的。 (不过,感谢 Nali4Freedom 的建议)

【问题讨论】:

如果我没看错的话,根据graph 的第一行,节点#0 只有一条边,它通向节点#1。所以path 的第一行(或者可能是第一列)应该是Inf 1 1 1 1 1。我错过了什么? 啊,我知道你怎么会混淆这个是的。 graph 中的每一行都列出了从该节点离开的边,而path 中的每一行都包含到达node #[row_num] 的路径。例如,正确的path图表的第一行表示从节点5(col = 5)到节点0(row = 0),返回的下一个节点是节点2。到达节点0从节点 2 开始,我们使用节点 4,然后是节点 3,然后是节点 1,最后在我们的目的地使用节点 0。 【参考方案1】:

嘘!

我对添加 Wikipedia 的代码 sn-p 的结果进行了仔细观察,然后我想出了一个适配器,可以将其结果转换为我的结果,而无需调用单独的函数:

// Time to clean up the path graph...
for (int st_node = 0; st_node < this->size; st_node++)

    for (int end_node = 0; end_node < this->size; end_node++)
    
        int mid_node = this->path[st_node][end_node];

        if (mid_node == INF)
        
            // There is no mid_node, it's probably just a single step.
            if (this->graph[st_node][end_node] != INF)
            
                this->path[st_node][end_node] = st_node;
            

         else 
            // The mid_node may be part of a multi-step, find where it leads.
            while (this->path[mid_node][end_node] != INF)
            
                if (this->path[mid_node][end_node] == mid_node)  break;   // Infinite loop
                if (this->path[mid_node][end_node] == INF)  break;    // Dead end

                mid_node = this->path[mid_node][end_node];
            

            this->path[st_node][end_node] = mid_node;

           // IF mid_node
       // FOR end_node
   // FOR st_node

本质上,当从节点 A 到节点 B 时,这是一个单一的步骤 (mid_node == INF) 通过添加边(如果它存在于原始图中)来补偿。或者,如果它指向的节点只是通往目标节点(this-&gt;path[mid_node][end_node] != INF) 的垫脚石,那么它会一直挖掘直到找到它通向的位置。

感谢大家的帮助,我想我只是需要有人大声思考!

【讨论】:

【参考方案2】:

***有一些很好的信息和pseudocode。基本上你只需填写 |V|x|V| 'next' 矩阵,其中元素 i,j 包含从节点 i 到节点 j 需要前往的顶点的索引。然后可以给出从 i 到 j 的最短路径作为从 i 到 next[i][j] 和从 next[i][j] 到 j 的路径。您继续像这样递归地分解路径,直到获得完整路径。

【讨论】:

相信我,我试了一下,但我的设置工作方式(默认值设置为 INF)无法正常工作。 :\

以上是关于使用 Floyd-Warshall 查找所有最短路径和距离的主要内容,如果未能解决你的问题,请参考以下文章

Floyd-Warshall 算法:获得最短路径

Floyd-Warshall 算法返回具有相同权重的每条最短路径

最短路径之Dijkstra算法和Floyd-Warshall算法

如何在 Floyd-Warshall 算法中输出最短路径?

如何在 Floyd-Warshall 算法中找到最短路径和最短成本

单源最短路(bellman-ford算法+dijkstra算法)+任意两点最短路(floyd-warshall算法)