2019sjtuC-带权无向图问题

题意理解:给定一张带权无向图,依次从中拿走第i个点,求剩下的点到其他点的最短距离之和

分析问题:我们假设一张六个点的带权无向图,顶点编号0~5,按照题意我们可以得到所求:

  • 拿掉0号点,求1,2,3,4,5分别到其他点的距离
  • 拿掉1号点,求2,3,4,5分别到其他点的距离
  • 拿掉2号点,求3,4,5分别到其他点的距离
  • 拿掉3号点,求4,5分别到其他点的距离
  • 拿掉4号点,求5分别到其他点的距离
  • 拿掉5号点

我们倒着看分析过程:

  • 拿掉5号点
  • 拿掉4号点,求5分别到其他点的距离
  • 拿掉3号点,求4,5分别到其他点的距离
  • 拿掉2号点,求3,4,5分别到其他点的距离
  • 拿掉1号点,求2,3,4,5分别到其他点的距离
  • 拿掉0号点,求1,2,3,4,5分别到其他点的距离

可以发现,依托floyd算法,我们让k从n-1开始遍历,每对k进行一次floyd算法,再对k及更大的点的最短路径求和

最终答案的总和即为所求(画个图好理解)

#include <iostream>
#include <algorithm>

using namespace std;
const int N=510;
int mat[N][N];
int n;

int main()
{
    while(cin>>n)
    {   int res=0;
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
                cin>>mat[i][j];

        for(int k=n-1;k>0;k--){
            for(int i=0;i<n;i++)
                for(int j=i+1;j<n;j++)
                    if(mat[i][k]+mat[k][j]<mat[i][j])
                        mat[i][j]=mat[j][i]=mat[i][k]+mat[k][j];

            for(int m=k;m<n;m++)
                for(int t=m+1;t<n;t++)
                    res+=2*mat[m][t];
        }

        cout<<res<<endl;
    }
    return 0;
}

问题:为什么k不正向遍历:

因为如果正向遍历的话,举个例子:在删去0号点时,求解ans需要 借助了比k>0的点的最短路径,而此时k并未更新到位。

一句话,正向遍历时会用到还未更新的点,所以每删去一个点要更新一次dist数组!!

而反向遍历时,只需要比k更大的点更新,所以可以在一次floyd的过程中顺带求出ans,因此本题反向遍历。

全部评论

相关推荐

评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务