题目描述 Description
DQ星球的世界末日就要到了,可是诺亚方舟还没有制造完成。为了制造诺亚方舟这个星球上的所有国家都站在统一战线。现在一共有n个国家,一个国家到另一个国家都有一条且仅有一条通信渠道,且这个渠道有一个距离,这样就形成了一个有向完全图。 世界末日的预兆已经来了,世界上很多东西都在遭到不明原因的破坏,包括这些通信渠道。现在为了联合制造出诺亚方舟,需要统计所有国家对(a到b和b到a是不同的)之间通信最短距离之和。即需要求出表示i国家与j国家之间的最小距离。可是每隔一段时间就有一些渠道会被破坏,现在DQ星球的首领急需要你来解决这个问题。
输入描述 Input Description
对于每组数据,第一行是一个n,表示有n个国家,接下来有n行,每有n个整数。第i行第j列的数字表示国家i到国家j的通信渠道距离(距离不大于10000)。接下来是一个数字m,表示在可以预知的未来中会有m次破坏会施加到通信渠道中,每次破坏只能破坏一条渠道,一条渠道可以被破坏多次, 但是第一次破坏这条渠道就无法再发送信息。接下来有m行,每行两个整数a、b,表示国家a到国家b的通信渠道遭到破坏。
输出描述 Output Description
对于每组数据,输出m行,第i行表示第i次破坏后对应的答案是多少。如果存在两个国家无法相互到达,输出INF。
样例输入 Sample Input
3
0 1 1
1 0 1
1 1 0
4
1 2
1 2
2 3
2 1
样例输出 Sample Output
7
7
8
INF
数据范围及提示 Data Size & Hint
40%的数据中1 < n<=50,1< m<=50;
100%的数据中1 < n<=200,1< m<=200;
终于找到一道floyd!离线!!
首先,先把该破坏的都破坏了,再对剩下的邻接矩阵做floyd。
然后现在就拿到了第m次破坏后的答案。
之后从m-1次开始往前把边恢复回去。由于现在的图只能被这个被破坏的边更新,所以就n^2枚举点,更新邻接矩阵,然后再累加,得到m-1次破坏的答案,以此类推。
代码:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int size=450;
const int INF=23333333;
int G[size][size];
struct haha{
int f,t,d;
int ans;
}ans[size];
int main()
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
scanf("%d",&G[i][j]);
}
}
int m;
scanf("%d",&m);
for(int i=1;i<=m;i++)
{
scanf("%d%d",&ans[i].f,&ans[i].t);
ans[i].d=G[ans[i].f][ans[i].t];
G[ans[i].f][ans[i].t]=INF;
}
for(int k=1;k<=n;k++)
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
G[i][j]=min(G[i][j],G[i][k]+G[k][j]);
}
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
ans[m].ans+=G[i][j];
}
}
for(int k=m;k>=1;k--)
{
int f=ans[k].f;
int t=ans[k].t;
int d=ans[k].d;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
G[i][j]=min(G[i][j],G[i][f]+d+G[t][j]);
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
ans[k-1].ans+=G[i][j];
}
}
}
for(int i=1;i<=m;i++)
{
if(ans[i].ans>=INF) puts("INF");
else printf("%d\n",ans[i].ans);
}
return 0;
}