T3:
给定一张 n 个点的有向带权完全图,和一个数组 a[] ,请按顺序删除数组中的点,请求出在删除点 a[i] 以前,所有未删除点对之间的最短路的值的和。
输入
4
0 3 1 1
6 0 400 1
2 4 0 1
1 1 1 0
4 1 2 3
输出
17 23 404 0倒着加边更新最短路
#include<bits/stdc++.h>
using namespace std;
int dis[505][505],a[505],q[505];
int n,tot;
long long ans[505];
int main(){
// freopen("shortest.in","r",stdin);
// freopen("shortest.out","w",stdout);
scanf("%d",&n);
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j)
scanf("%d",&dis[i][j]);
for(int i=1;i<=n;++i) scanf("%d",&a[i]);
for(int i=n;i>=1;--i){
int d=a[i];
for(int j1=1;j1<=tot;++j1)
for(int k1=1;k1<=tot;++k1){
int j=q[j1],k=q[k1];
if(dis[d][j]+dis[j][k]<dis[d][k]) dis[d][k]=dis[d][j]+dis[j][k];
if(dis[k][j]+dis[j][d]<dis[k][d]) dis[k][d]=dis[k][j]+dis[j][d];
}
for(int j1=1;j1<=tot;++j1)
for(int k1=1;k1<=tot;++k1){
int j=q[j1],k=q[k1];
if(dis[j][d]+dis[d][k]<dis[j][k]) dis[j][k]=dis[j][d]+dis[d][k];
}
q[++tot]=a[i];
for(int j1=1;j1<=tot;++j1)
for(int k1=1;k1<=tot;++k1){
int j=q[j1],k=q[k1];
ans[i]=ans[i]+(long long)dis[j][k];
}
}
for(int i=1;i<=n;++i) cout<<ans[i]<<" ";
return 0;
}