B. Greg and Graph
题意:n个节点的图,每次操作删除一个节点。求每次操作之前,所有的图中的有序对(i, j)的最短路径之和。
思路:n <= 500, 弗洛伊德最短路径算法。因为每次的操作是删除节点,所以可以考虑将操作反着来,每次往图中添加节点,每添加一个节点更新一下最短路径。
总结:因为要添加的节点已经存储在了图中,所以不需要再将该节点作为终点去求最短路径了,只需要将该节点作为中转节点去求最短路径就可以。
debug一个数据溢出问题,调了半个小时。最后发现是在输出的时候对long long容器使用了(int v : ans)输出,真是个傻逼。
void solve(){
int n;
cin >> n;
vector<vector<int>> am(n, vector<int>(n));
vector<int> order(n);
vector<long long> ans(n, 0);
for (int i = 0; i < n; ++i){
for (int j = 0; j < n; ++j){
cin >> am[i][j];
}
}
for (int i = 0; i < n; ++i){
cin >> order[i];
order[i] --;
}
vector<int> has;
for (int i = n - 1; i >= 0; --i){
int k = order[i];
for (int u = 0; u < n; ++u){
for (int v = 0; v < n; ++v){
//checkMin(am[u][v], am[u][k] + am[k][v]);
am[u][v] = min(am[u][v], am[u][k] + am[k][v]);
}
}
for (int u = n - 1; u >= i; --u){
for (int v = n - 1; v >= i; --v){
ans[i] += am[order[u]][order[v]];
}
}
}
for (int i = 0; i < n; ++i){
cout << ans[i] << " \n"[i == n - 1];
}
}