使用 Floyd 算法找到最短路径

Posted

技术标签:

【中文标题】使用 Floyd 算法找到最短路径【英文标题】:Find the shortest path with Floyd algorithm 【发布时间】:2015-09-12 05:42:24 【问题描述】:

我有一个包含数字 0 和 1 的邻接矩阵。如果一个节点到另一个节点没有边,则该字段为0,否则该字段标记为1。

那么,如果邻接矩阵中的某个字段为0,则节点之间不存在边,否则存在权重为1的边。

现在,我已经应用 Floyd 算法来找出从任何节点到其他节点的最短路径。但我没有得到正确的解决方案。

这是我的弗洛伊德算法实现。

void Floyd_Warshal(int graph[Nodes][Nodes], int D[Nodes][Nodes])

    for (int i = 0; i < Nodes; i++)
    
        for (int j = 0; j < Nodes; j++)
        
            if (graph[i][j] == 0)  graph[i][j] = INT_MAX; 
            D[i][j] = graph[i][j];
        
    
    for (int k = 0; k < Nodes; k++) 
        for (int i = 0; i < Nodes; i++)
        
            for (int j = 0; j < Nodes; j++)
            
                if (D[i][j] > D[i][k] + D[k][j]) 
                    D[i][j] = D[i][k] + D[k][j];
                
            
        
    

我已将 0 设置为 INT_MAX,以便为算法构建标准矩阵,但我没有得到正确的解决方案。

另外,这是我的矩阵的一个例子:

  A B C D
A 0 0 1 0
B 1 1 0 1
C 0 0 1 0
D 1 0 0 0

将矩阵应用于算法后,矩阵中的任何 0 都将转换为INT_MAX。我希望得到 2 或 1 的权重,但我得到了意想不到的值,例如 -2712323...

【问题讨论】:

你能附上一个邻接矩阵的例子吗? ...以及预期的输出和你得到的输出。您还可以澄清“如果从特定节点到任何其他节点没有任何边,则该字段将为0,否则该字段将标记为1”是什么意思。 @ralzaul 我已更新帖子以添加示例。 @Petr 我的意思是,例如,如果节点 A 到节点 C 之间没有任何边,则矩阵中 A-C 的值将为 0,否则该值为 1。 @VCL_D,我已经改写了你的问题,以便更清楚,因为当你相同的“任何其他节点”时,这看起来你的意思是 all other节点,而不仅仅是与邻接矩阵中该元素对应的特定其他节点。 【参考方案1】:

你得到非常大的负值的原因是整数溢出。

如果没有边,则设置D[i][j]=INT_MAX。但后来

            if (D[i][j] > D[i][k] + D[k][j]) 
                D[i][j] = D[i][k] + D[k][j];

如果从ik 和从kj 没有边,那么总和将溢出,结果将为负数。之后,您的算法会认为从这个i 到这个j 有一条很短(很大的负数)路径,这会毒害所有其他路径。

如果INT_MAX,我建议你使用INT_MAX/2

【讨论】:

(或将测试写为if (D[i][j] - D[k][j] &gt; D[i][k]) ,假设非负距离不会溢出。)

以上是关于使用 Floyd 算法找到最短路径的主要内容,如果未能解决你的问题,请参考以下文章

数据结构8——最短路径

Floyd最短路(带路径输出)

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

Floyd

a*算法求最短路径和floyd还有dijsktra算法求最短路径的区别?

Bellman-Ford算法——为什么要循环V-1次?图有n个点,又不能有回路,所以最短路径最多n-1边。又因为每次循环,至少relax一边所以最多n-1次就行了!