这题要求的是一个类似于动态最短路的东西
乍一看可能有点棘手,实际上是三个for循环的题目,滑稽
我们思考一下加入一个点会产生什么影响,所有和它相连的边,都会被判断一次三角形不等式是否可以被破坏,这像什么,Floyd啊,我们每次删除的点,是不是很像我们枚举的断点,我们倒序读入,不就变成了按照一定顺序枚举断点的floyd了吗
细节不多,但是会坑
我们floyd过程中更新时是不用判断这个点在不在图中的,但是统计答案要
因为一个点一旦加入图里,要求一定立刻是最短路,所以要用在他之前的点求好他的值,在他进入图之前,我们不统计他的答案就可以了,就好像从
O
(
N
4
)
O(N^4)
O(N4)到了
O
(
N
3
)
O(N^3)
O(N3)
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<queue>
using namespace std;
const int maxn = 507;
int f[maxn],n;
long long out[maxn];
int dis[maxn][maxn],in[maxn];
int main(){
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=n;i>=1;i--){
scanf("%d",&f[i]);
}
for(int tt=1;tt<=n;tt++){
int k=f[tt];in[k]=1;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(i!=j&&i!=k&&j!=k){
dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
}
}
}
long long sum=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(in[i]&&in[j])sum+=dis[i][j];
out[tt]=sum;
}
for(int i=n;i>=1;i--){
printf("%lld\n",out[i]);
}
}