Codeforces 25C. Roads in Berland(最短路松弛操作)

题意:

给你一个dis[i][j]矩阵,代表从i顶点到j顶点的最短路,再给你k条路,每次将其加入地图中,问加入后各个顶点之间最短路的和

思路:

如果加入的道路距离比原来的距离长,则不需要修改答案

如果小于原来的距离,则先将原来的距离更新,枚举起点与重点判断能否进行松弛操作

松弛操作:dis[i][j]>dis[i][v]+w+dis[u][j]

     ②dis[i][j]>dis[i][u]+w+dis[v][j]

#include<iostream>
#include<algorithm>
#include<cstring>
 using namespace std;
 typedef long long ll;
 const int maxn=305;
 ll dis[maxn][maxn];
 ll n,ans=0,m,u,v,w;
 void solve()
 {
     for(int i=1;i<=n;i++){
         for(int j=1;j<=n;j++){
            if(dis[i][j]>dis[i][v]+w+dis[u][j]){
                ans-=dis[i][j]-(dis[i][v]+w+dis[u][j]);
                dis[i][j]=dis[j][i]=dis[i][v]+w+dis[u][j];
            }
            if(dis[i][j]>dis[i][u]+w+dis[v][j]){
                ans-=dis[i][j]-(dis[i][u]+w+dis[v][j]);
                dis[i][j]=dis[j][i]=dis[i][u]+w+dis[v][j];
             }
     }
 }
}
 int main()
 {
     scanf("%lld",&n);
     for(int i=1;i<=n;i++)
         for(int j=1;j<=n;j++){
             scanf("%lld",&dis[i][j]);
             ans+=dis[i][j];
         }
    ans/=2;
    scanf("%lld",&m);
    for(int i=1;i<=m;i++){
        scanf("%lld%lld%lld",&u,&v,&w);
        if(dis[u][v]<=w){
            cout<<ans<<" ";
            continue;
        }
        else{
            ans-=dis[u][v]-w;
            dis[u][v]=dis[v][u]=w;
            solve();
            cout<<ans<<" ";
        }
    }
    return 0;
 }

猜你喜欢

转载自www.cnblogs.com/overrate-wsj/p/12272962.html