Codevs 2011 最小距离和

来源:互联网 发布:淘宝网儿童帽子 编辑:程序博客网 时间:2024/05/17 13:06

题目描述 Description
DQ星球的世界末日就要到了,可是诺亚方舟还没有制造完成。为了制造诺亚方舟这个星球上的所有国家都站在统一战线。现在一共有n个国家,一个国家到另一个国家都有一条且仅有一条通信渠道,且这个渠道有一个距离,这样就形成了一个有向完全图。 世界末日的预兆已经来了,世界上很多东西都在遭到不明原因的破坏,包括这些通信渠道。现在为了联合制造出诺亚方舟,需要统计所有国家对(a到b和b到a是不同的)之间通信最短距离之和。即需要求出表示i国家与j国家之间的最小距离。可是每隔一段时间就有一些渠道会被破坏,现在DQ星球的首领急需要你来解决这个问题。

输入描述 Input Description
对于每组数据,第一行是一个n(n<200),表示有n个国家,接下来有n行,每有n个整数。第i行第j列的数字表示国家i到国家j的通信渠道距离(距离不大于10000)。接下来是一个数字m(m<200),表示在可以预知的未来中会有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

据说这是2013年辽宁省选题。。害怕。。然而并不难,主要在于。。有没有长脑子。。比如我第一次交这题。。
不说废话了。。。很容易想出的是用floyd求解,毕竟数据范围只有200,然后对于每次破坏如果不是直接相连,那就再跑一次floyd。如果直接相连并且没有其他的路线走过这条边,那么我们不管它就是了,对最终结果没有任何影响。
第一次交的时候忘记判断这条边有没有破坏过和破坏以后对其他结果有没有影响,于是华丽丽的TLE了,只拿到了4个点。
(40%数据的代码)

#include<iostream>#include<cstdio>#include<algorithm>using namespace std;const int maxn = 233;const int INF = 10e7-1;int edge[maxn][maxn],temp[maxn][maxn];int n,m,ans;int main(){    cin>>n;    for(int i=1;i<=n;i++)    for(int j=1;j<=n;j++)    scanf("%d",&edge[i][j]);    cin>>m;    bool vis=0;    for(int q=1;q<=m;q++)    {        ans=0;        if(vis==0)        {            int x,y;            scanf("%d%d",&x,&y);            edge[x][y]=INF;            for(x=1;x<=n;x++)            for(y=1;y<=n;y++) temp[x][y]=edge[x][y];            for(int k=1;k<=n;k++)            for(int i=1;i<=n;i++)            for(int j=1;j<=n;j++)            if(temp[i][j]>temp[i][k]+temp[k][j] )                temp[i][j]=temp[i][k]+temp[k][j];            for(int i=1;i<=n;i++)            {                for(int j=1;j<=n;j++)                {                    if(temp[i][j]==INF)                     {                        vis=1;                        puts("INF\n");                        break;                    }                    ans+=temp[i][j];                }                if(vis==1) break;            }            if(vis==0)            printf("%d\n",ans);        }        else        puts("INF\n");    }    return 0;}

然后仔细想了想发现可以优化,于是A掉了。
代码如下:

#include <iostream>#include<cstdio>using namespace std;int n,i,j,map[201][201],SP[201][201],k,answer=0,m,a,b,l;bool LW[201][201]={};int main(){    cin>>n;    for (i=1;i<=n;i++)    for (j=1;j<=n;j++)    cin>>map[i][j];    for (i=1;i<=n;i++)    for (j=1;j<=n;j++)    SP[i][j]=map[i][j];    for (i=1;i<=n;i++)    for (j=1;j<=n;j++)    for (k=1;k<=n;k++)    if (SP[j][k]>SP[j][i]+SP[i][k])    {        SP[j][k]=SP[j][i]+SP[i][k];        LW[j][k]=1;    }    for (i=1;i<=n;i++)    for (j=1;j<=n;j++)    answer+=SP[i][j];    cin>>m;    for (i=1;i<=m;i++)    {        cin>>a>>b;        if (LW[a][b])        goto abc;        map[a][b]=1000000001;        for (j=1;j<=n;j++)        for (k=1;k<=n;k++)        SP[j][k]=map[j][k];        for (j=1;j<=n;j++)        for (k=1;k<=n;k++)        for (l=1;l<=n;l++)        SP[k][l]=min(SP[k][j]+SP[j][l],SP[k][l]);        answer=0;        for (j=1;j<=n;j++)        for (k=1;k<=n;k++)        answer+=SP[j][k];        abc:        {            if(answer>10e7)            puts("INF\n");            else            cout<<answer<<endl;        }    }}
0 0
原创粉丝点击