Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/372.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Floyd warshall实施似乎缺少最短路径_Java_Algorithm_Floyd Warshall - Fatal编程技术网

Java Floyd warshall实施似乎缺少最短路径

Java Floyd warshall实施似乎缺少最短路径,java,algorithm,floyd-warshall,Java,Algorithm,Floyd Warshall,我正在收集floyd warshall找到的最短路径。对于这个特殊的图,1->3的最短路径是5,并且有两条具有此权重的路径:1->4->2->3和1->4->3 我不确定显示图表的最佳方式,因此我将使用矩阵,如果您知道更好的替代方法,请随意建议其他方式 //i = infinity, no path exists initially //for u==v, 0 1 2 3 4 1| 0 i 8 2 2| i 0 2 i 3| i 7

我正在收集floyd warshall找到的最短路径。对于这个特殊的图,1->3的最短路径是5,并且有两条具有此权重的路径:1->4->2->3和1->4->3

我不确定显示图表的最佳方式,因此我将使用矩阵,如果您知道更好的替代方法,请随意建议其他方式

 //i = infinity, no path exists initially
 //for u==v, 0
    1   2   3   4
1|  0   i   8   2
2|  i   0   2   i
3|  i   7   0   6
4|  i   1   3   0
所以当我运行我的代码时,我从1->3得到的最短路径数仅为1,但正如我前面提到的,有两种方法

以下是算法的实现:

 //count[][] is initialized with a 0 if no path between [u][v], and 1 at [u][v] if there is a weight at [u][v]. 

    for (int k = 1; k <= N; k++){
        for (int i = 1; i <= N; i++){
            for (int j = 1; j <= N; j++){
                if (dist[i][j] > dist[i][k] + dist[k][j]){
                    dist[i][j] = dist[i][k] + dist[k][j];
                    counts[i][j] = 1;
                }
                else if (dist[i][j] == dist[i][k] + dist[k][j] && k != i && k != j){
                    counts[i][j] ++;                
                }
            }
        }
    }
更新:当k=4,i=1,j=3时,我们逐行通过代码,找到权重为5的1->3的最短路径


更新:阅读Floyd Warshall算法的维基百科条目,我发现当k=4时,我们正在检查穿过顶点{1,2,3,4}的路径。然而,在k的每次迭代中,我们只会看[1][3]一次。我想也许这就是问题所在

如果使用二维int数组存储数据,最好将双循环从0改为N-1,以避免任何潜在错误。我这样做了,结果是正确的(从1->3的最短距离是5)。以下是更新的代码和打印输出:

     //count[][] is initialized with a 0 if no path between [u][v], and 1 at [u][v] if there is a weight at [u][v]. 
    int N = 4;
    int max = 1000000;
    int[][] dist = new int[N][N];
    int[][] counts = new int[N][N];
    dist[0][0] = 0;         dist[0][1] = max;   dist[0][2] = 8;     dist[0][3] = 2;
    dist[1][0] = max;       dist[1][1] = 0;     dist[1][2] = 2;     dist[1][3] = max;
    dist[2][0] = max;       dist[2][1] = 7;     dist[2][2] = 0;     dist[2][3] = 6;
    dist[3][0] = max;       dist[3][1] = 1;     dist[3][2] = 3;     dist[3][3] = 0;
    //initialize counts
    for (int i=0; i<N; i++){
        for (int j=0; j<N; j++){
            if (dist[i][j]<max){
                counts[i][j]=1;
            }
        }
    }
    for (int k = 0; k < N; k++){
        for (int i = 0; i < N; i++){
            for (int j = 0; j < N; j++){
                if (dist[i][j] > dist[i][k] + dist[k][j]){
                    dist[i][j] = dist[i][k] + dist[k][j];
                    counts[i][j] = 1;
                }
                else if (dist[i][j] == dist[i][k] + dist[k][j] && k != i && k != j){
                    counts[i][j] ++;                
                }
            }
        }
    }
    System.out.println("i  1 2 3 4");
    for (int i=0; i<N; i++){
        System.out.print(i+1 + ": ");
        for (int j=0; j<N; j++){
            System.out.print(dist[i][j]>=max ? "i ":dist[i][j] + " ");
        }
        System.out.println();
    }
    System.out.println();
    System.out.println("i  1 2 3 4");
    for (int i=0; i<N; i++){
        System.out.print(i+1 + ": ");
        for (int j=0; j<N; j++){
            System.out.print(counts[i][j] + " ");
        }
        System.out.println();
    }
//如果[u][v]之间没有路径,则使用0初始化计数[],如果[u][v]处有权重,则使用1初始化计数[]。
int N=4;
int max=1000000;
int[][]dist=新int[N][N];
int[][]计数=新的int[N][N];
dist[0][0]=0;距离[0][1]=最大值;区[0][2]=8;区[0][3]=2;
距离[1][0]=最大值;dist[1][1]=0;区[1][2]=2;距离[1][3]=最大值;
距离[2][0]=最大值;区[2][1]=7;dist[2][2]=0;区[2][3]=6;
距离[3][0]=最大值;地区[3][1]=1;区[3][2]=3;dist[3][3]=0;
//初始化计数

对于(int i=0;i,您提出的算法有问题。不是代码。您的更新表明您已经接近它了

您有两条从4到3的最短路径:
4-->3
4-->2-->3
。两者的长度都是3(当k增加到4时,您的算法将建立这一长度)。 因此,在最后一次迭代中,当
k=4
时,您的程序将询问,如果我通过4,从1到3的路径是否会更短?然后它将决定
为8>2+3
-是! 您将最短路径数设置为1。但有2个子路径从4到3,您将不再考虑

这是因为Floyd Warshall一次只考虑一个顶点(k),并检查通过该点的路径是否缩短。因此,您的程序只计算具有不同倒数第二个顶点的最短路径的数量(位于目的地之前的那些)。它没有考虑到这样一个事实,即即使到达最后一个点,也有两条最短路径可用

下面的例子应该说明这一点:

在形状为“V”的图形中,有多少条路径可供您到达底部(最低点)。您的程序将正确地查看底部,例如2。但当被问及形状为“Y”的图形时,您的程序将再次查看底部,并错误地得出只有一条路径通向底部的结论

幸运的是,您选择的测试用例抓住了这个问题

不幸的是,我不认为一个小的编辑就能解决它。这是因为Floyd Warshall算法保证所有对之间的最短路径。不是所有对之间的所有最短路径。但是如果您只对该算法找到的路径感兴趣,而不是将计数初始化为1并增加它们通过1,初始化并增加为要经过的顶点找到的最短子路径的数量。(在这种特殊情况下为2)

     //count[][] is initialized with a 0 if no path between [u][v], and 1 at [u][v] if there is a weight at [u][v]. 
    int N = 4;
    int max = 1000000;
    int[][] dist = new int[N][N];
    int[][] counts = new int[N][N];
    dist[0][0] = 0;         dist[0][1] = max;   dist[0][2] = 8;     dist[0][3] = 2;
    dist[1][0] = max;       dist[1][1] = 0;     dist[1][2] = 2;     dist[1][3] = max;
    dist[2][0] = max;       dist[2][1] = 7;     dist[2][2] = 0;     dist[2][3] = 6;
    dist[3][0] = max;       dist[3][1] = 1;     dist[3][2] = 3;     dist[3][3] = 0;
    //initialize counts
    for (int i=0; i<N; i++){
        for (int j=0; j<N; j++){
            if (dist[i][j]<max){
                counts[i][j]=1;
            }
        }
    }
    for (int k = 0; k < N; k++){
        for (int i = 0; i < N; i++){
            for (int j = 0; j < N; j++){
                if (dist[i][j] > dist[i][k] + dist[k][j]){
                    dist[i][j] = dist[i][k] + dist[k][j];
                    counts[i][j] = 1;
                }
                else if (dist[i][j] == dist[i][k] + dist[k][j] && k != i && k != j){
                    counts[i][j] ++;                
                }
            }
        }
    }
    System.out.println("i  1 2 3 4");
    for (int i=0; i<N; i++){
        System.out.print(i+1 + ": ");
        for (int j=0; j<N; j++){
            System.out.print(dist[i][j]>=max ? "i ":dist[i][j] + " ");
        }
        System.out.println();
    }
    System.out.println();
    System.out.println("i  1 2 3 4");
    for (int i=0; i<N; i++){
        System.out.print(i+1 + ": ");
        for (int j=0; j<N; j++){
            System.out.print(counts[i][j] + " ");
        }
        System.out.println();
    }