Floyd - Greg and Graph - CodeForces 295B
题意:
给 定 一 个 n 个 点 的 有 向 完 全 图 , 给定一个n个点的有向完全图, 给定一个n个点的有向完全图,
现 在 依 次 删 除 n 个 点 , 现在依次删除n个点, 现在依次删除n个点,
删 除 每 个 点 之 前 , 输 出 当 前 图 中 任 意 两 点 之 间 的 最 短 距 离 之 和 。 删除每个点之前,输出当前图中任意两点之间的最短距离之和。 删除每个点之前,输出当前图中任意两点之间的最短距离之和。
输入:
首 行 一 个 正 整 数 n , 表 示 点 的 个 数 。 首行一个正整数n,表示点的个数。 首行一个正整数n,表示点的个数。
接 着 输 入 一 个 n × n 的 邻 接 矩 阵 w 。 接着输入一个n×n的邻接矩阵w。 接着输入一个n×n的邻接矩阵w。
最 后 一 行 输 入 n 个 数 , 表 示 依 次 删 除 这 n 个 点 。 最后一行输入n个数,表示依次删除这n个点。 最后一行输入n个数,表示依次删除这n个点。
输出:
n 个 数 , 表 示 依 次 删 除 n 个 点 之 前 , 任 意 两 点 之 间 的 最 短 距 离 之 和 。 n个数,表示依次删除n个点之前,任意两点之间的最短距离之和。 n个数,表示依次删除n个点之前,任意两点之间的最短距离之和。
Examples
Input
1
0
1
Output
0
Input
2
0 5
4 0
1 2
Output
9 0
Input
4
0 3 1 1
6 0 400 1
2 4 0 1
1 1 1 0
4 1 2 3
Output
17 23 404 0
数据范围:
1 ≤ n ≤ 500 , 1 ≤ w i j ≤ 1 0 5 , w i i = 0 1 ≤ n ≤ 500,1 ≤ w_ {ij} ≤ 10^5,w_{ii} = 0 1 ≤ n ≤ 500,1 ≤ wij ≤ 105,wii = 0
分析:
要 求 任 意 两 点 之 间 的 距 离 , 考 虑 F l o y d 算 法 。 要求任意两点之间的距离,考虑Floyd算法。 要求任意两点之间的距离,考虑Floyd算法。
最 暴 力 的 想 法 : 每 次 删 除 一 个 点 就 更 新 一 次 图 , 再 对 新 图 跑 一 遍 F l o y d , 时 间 复 杂 度 为 O ( n 4 ) 。 最暴力的想法:每次删除一个点就更新一次图,再对新图跑一遍Floyd,时间复杂度为O(n^4)。 最暴力的想法:每次删除一个点就更新一次图,再对新图跑一遍Floyd,时间复杂度为O(n4)。
考 虑 F l o y d 算 法 最 外 层 k 的 含 义 , 表 示 考 虑 了 前 k 个 点 的 最 短 路 , 考虑Floyd算法最外层k的含义,表示考虑了前k个点的最短路, 考虑Floyd算法最外层k的含义,表示考虑了前k个点的最短路,
当 循 环 过 第 k 层 时 , 前 k 个 点 , 任 意 两 点 之 间 的 距 离 就 是 最 短 距 离 。 当循环过第k层时,前k个点,任意两点之间的距离就是最短距离。 当循环过第k层时,前k个点,任意两点之间的距离就是最短距离。
因 此 , 我 们 将 依 次 删 除 n 个 点 反 过 来 看 作 依 次 添 加 n 个 点 , 倒 序 读 入 删 除 点 的 顺 序 即 添 加 点 的 顺 序 。 因此,我们将依次删除n个点反过来看作依次添加n个点,倒序读入删除点的顺序即添加点的顺序。 因此,我们将依次删除n个点反过来看作依次添加n个点,倒序读入删除点的顺序即添加点的顺序。
根 据 添 加 点 的 顺 序 来 跑 F l o y d 算 法 。 根据添加点的顺序来跑Floyd算法。 根据添加点的顺序来跑Floyd算法。
只 要 按 照 添 加 的 顺 序 来 累 加 即 可 。 只要按照添加的顺序来累加即可。 只要按照添加的顺序来累加即可。
代码:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define ll long long
using namespace std;
const int N=510;
int n;
ll g[N][N];
int ver[N];
ll ans[N];
void floyd()
{
for(int u=1;u<=n;u++)
{
int k=ver[u];
for(int v=1;v<=n;v++)
for(int w=1;w<=n;w++)
{
int i=ver[v], j=ver[w];
g[i][j]=min(g[i][j],g[i][k]+g[k][j]);
if(v<=u&&w<=u) ans[u]+=g[i][j]; //点的顺序
}
}
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
cin>>g[i][j];
for(int i=n;i;i--) scanf("%d",&ver[i]);
floyd();
for(int i=n;i;i--) cout<<ans[i]<<' ';
return 0;
}