Floyd-Warshall实施中的错误是什么?

时间:2015-09-15 08:17:45

标签: algorithm graph shortest-path floyd-warshall

以下是问题链接:http://codeforces.com/contest/295/problem/B

Greg有一个称重的有向图,由n个顶点组成。在该图中,任何一对不同的顶点在两个方向上都具有边缘。 Greg喜欢玩图表,现在他发明了一款新游戏:

游戏包含n个步骤。 在第i步,Greg从图中移除顶点数xi。当Greg移除顶点时,他还会移除进出该顶点的所有边。 在执行每个步骤之前,Greg想要知道所有剩余顶点对之间的最短路径的长度总和。最短路径可以通过任何剩余的顶点。 帮助Greg,在每一步之前打印所需总和的值。

输入:

第一行包含整数n(1≤n≤500) - 图中顶点的数量。

接下来n行每行包含n个整数 - 图形邻接矩阵:第i行中的第j个数aij(1≤aik≤105,aii = 0)表示从顶点i开始的边的权重到顶点j。

下一行包含n个不同的整数:x1,x2,...,xn(1≤xi≤n) - Greg删除的顶点。

输出:

打印n个整数 - 第i个数字等于第i步之前所需的总和。

所以,基本上我的方法是在删除任何顶点之前运行Floyd-Warshall算法,并且为了删除,我只需要在两行的邻接矩阵中将要删除的顶点的值设置为INT_MAX和列。

基本上,此循环位于main

    for (int h = 0; h < n; h++)
    {
        func();
        int val = arr[h];   // arr contains the vertices to be deleted
        for ( i = 1; i <= n; i++ )
            dist[val][i] = INT_MAX;
        for ( i = 1; i <= n; i++ )
            dist[i][val] = INT_MAX;
    }

这是我对Flloyd Warshall算法的实现:

void func () 
{
    //int i,j,k;
    ans = 0;
    for ( i = 1; i <= n; i++ )
    {
        for ( j = 1; j <= n; j++ )
        {
            if (i == j)
                val[i][j][0] = 0;
            else if (dist[i][j] != 0)
                val[i][j][0] = dist[i][j];
            else
                val[i][j][0] = INT_MAX;
        }
    }
    for (k = 1; k <= n; k++)
        for ( i = 1; i <= n; i++ )
            for ( j = 1; j <= n; j++ )
                val[i][j][k] = min(val[i][j][k-1],val[i][k][k-1]+val[k][j][k-1]);   
    //int ans = 0;
    for ( i = 1; i <= n; i++ )
        for ( j = 1; j <= n; j++ )
            ans = ans + val[i][j][n];
    cout<<ans<<"\t";
}

这里,val是我创建的全局三维矩阵,arr包含要删除的顶点。但是,当我运行这个逻辑时,它最初只给出正确的答案,即没有删除任何顶点时。但在那之后,它给出了错误的价值。我不明白为什么?我的逻辑是不正确的?

2 个答案:

答案 0 :(得分:1)

一件看起来很奇怪的事情是,最后你要计算所有剩余顶点对的总和,但你的循环只是在所有顶点上:

for ( i = 1; i <= n; i++ )
    for ( j = 1; j <= n; j++ )
        ans = ans + val[i][j][n];

答案 1 :(得分:0)

这是错误的方法,将获得TLE...。 按照这种方式

U应该牢记对floyd warshall算法的理解。

首先要弄清楚自己,然后讲到这一点,按照这种算法,您可以按任何顺序设计中间元素(k)。因此,这里有n个步骤,这意味着将按给定的顺序删除n个节点……这意味着您可以按此给定的顺序设计您的中间元素..说给定的删除顺序集为[1,2,3]………………。

现在这意味着当删除1个顶点时,则每对最短路径的总和。然后,当2也被删除时,依此类推…………

现在以这种方式思考,当仅考虑删除不包含3的所有顶点时,在这里使用k(3)时,您可以求和剩下3个的总和,现在使k的值为(2)意味着仅2和剩下的3个现在被删除,现在求和........因此,如果u反转此答案,则当1 2 3剩余时,求和(不删除顶点),则1个被删除

这意味着几乎只有2,3个剩余的被删除,它们加起来…………。

所以,如果您对floyd warshall算法有个好主意,我认为这应该很清楚

基于上述想法,我在这里干净整洁的解决方案

https://github.com/joy-mollick/Problem-Solving-Solutions/blob/master/Codeforces-B%20-%20Greg%20and%20Graph.cpp