题意:
给你一个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; }