题目给一个有向带权图,给出一个删点序列,依次删去序列中点和相连的边,求每次删点前图中两两点间最短路之和,点数n不大,500……
渣渣觉得这是个好题……粘代码……
/*
回想求最小环,floyd第一重恰好枚举了用到的点
没有循环到的点不影响当前的最短路
时间倒流,一个个把点加上去,每次都在全局的最短路枚举
所以可以利用floyd性质来搞
注意松弛要循环整个图,统计循环添加上的部分就可以了
*/
#include <iostream>
using namespace std;
#define ll long long
const int N=501;
ll dist[N][N],s[N],x[N];
int main() {
int n; cin >> n;
for (int i=1; i<=n; i++)
for (int j=1; j<=n; j++) {
cin >> dist[i][j];
if (!dist[i][j]) dist[i][j]=9999999999999ll;
}
for (int i=1; i<=n; i++) cin >> x[i];
for (int k=n; k; k--) {
for (int i=1; i<=n; i++)
for (int j=1; j<=n; j++)
if (dist[i][x[k]]+dist[x[k]][j]<dist[i][j])
dist[i][j]=dist[i][x[k]]+dist[x[k]][j];
ll ans=0;
for (int i=n; i>=k; i--)
for (int j=n; j>=k; j--)
if (i!=j) ans+=dist[x[i]][x[j]];
s[k]=ans;
}
for (int i=1; i<=n; cout << s[i++] << ' ');
cout << endl; //system("pause");
return 0;
}