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

时间:2010-10-25 21:03:07

标签: c++ algorithm graph floyd-warshall

首先,一点背景:我正在努力构建一个带有基本图算法的简单图表类(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

并且这里是“path”变量中的所需值(通过从每个节点运行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的建议)

2 个答案:

答案 0 :(得分:2)

好哇!

我很好地盯着添加维基百科代码片段的结果,我想出了一个适配器,可以将结果转换成我的结果,而无需调用单独的函数:

// 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->path[mid_node][end_node] != INF)的垫脚石,那么它会挖掘直到它找到它所在的位置。

感谢帮助人员,猜猜我只是需要有人大声思考!

答案 1 :(得分:1)

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