没有递归的弗洛伊德-沃歇尔路径重建

Posted

技术标签:

【中文标题】没有递归的弗洛伊德-沃歇尔路径重建【英文标题】:Floyd-Warshall path reconstruction without recursion 【发布时间】:2018-11-04 04:51:40 【问题描述】:

我正在使用来自 here 的 Floyd-Warshall 算法。

import static java.lang.String.format;
import java.util.Arrays;



public class FloydWarshall 


    public static void main(String[] args) 
        int[][] weights = 1, 3, -2, 2, 1, 4, 2, 3, 3, 3, 4, 2, 4, 2, -1;
        int numVertices = 4;

        floydWarshall(weights, numVertices);
    

    static void floydWarshall(int[][] weights, int numVertices) 

        double[][] dist = new double[numVertices][numVertices];
        for (double[] row : dist)
            Arrays.fill(row, Double.POSITIVE_INFINITY);

        for (int[] w : weights)
            dist[w[0] - 1][w[1] - 1] = w[2];

        int[][] next = new int[numVertices][numVertices];
        for (int i = 0; i < next.length; i++) 
            for (int j = 0; j < next.length; j++)
                if (i != j)
                    next[i][j] = j + 1;
        

        for (int k = 0; k < numVertices; k++)
            for (int i = 0; i < numVertices; i++)
                for (int j = 0; j < numVertices; j++)
                    if (dist[i][k] + dist[k][j] < dist[i][j]) 
                        dist[i][j] = dist[i][k] + dist[k][j];
                        next[i][j] = next[i][k];
                    

        printResult(dist, next);
    

    static void printResult(double[][] dist, int[][] next) 
        System.out.println("pair     dist    path");
        for (int i = 0; i < next.length; i++) 
            for (int j = 0; j < next.length; j++) 
                if (i != j) 
                    int u = i + 1;
                    int v = j + 1;
                    String path = format("%d -> %d    %2d     %s", u, v,
                            (int) dist[i][j], u);
                    do 
                        u = next[u - 1][v - 1];
                        path += " -> " + u;
                     while (u != v);
                    System.out.println(path);
                
            
        
    

算法本身很清楚,但我不明白的是next 矩阵。根据我对i,j 的理解,索引应该是从节点 i 到节点 j 的路径上的最后一个先前节点。然后递归打印打印路径。但是这段代码在打印语句printResult 中使用了某种不同的方法。所以我的问题是矩阵next 到底是什么以及打印是如何工作的?

【问题讨论】:

【参考方案1】:

dist[i][j] = dist[i][k] + dist[k][j] 行说:从 i 到 j,经过 k,走从 i 到 k 的最短路径,然后是从 k 到 j 的最短路径。这里:next[i][j] = next[i][k] 它说从 i 到 j 时,首先去如果你从 i 到 k 会去的地方。

所以,u = next[u - 1][v - 1]; 行说:u 现在是从 u 到 v 路径上的下一个节点。

【讨论】:

以上是关于没有递归的弗洛伊德-沃歇尔路径重建的主要内容,如果未能解决你的问题,请参考以下文章

题解灾后重建——(floyd)

[从今天开始修炼数据结构]图的最短路径 —— 迪杰斯特拉算法和弗洛伊德算法的详解与Java实现

[Python] 弗洛伊德(Floyd)算法求图的直径并记录路径

图(最短路径算法————迪杰斯特拉算法和弗洛伊德算法).RP

弗洛伊德思想题目

数据结构 图 最短路径问题 迪杰斯特拉算法和弗洛伊德算法问题