2017冬季24集训模拟题-24星球的末日(Floyd)

24 星球的末日
【问题描述】
24 星球的世界末日就要到了 , 可是诺亚方舟还没有制造完成 。 为了制造诺亚
方舟这个星球上的所有国家都站在统一战线 。 现在一共有n个国家 , 一个国家到
另一个国家都有一条且仅有一条通信渠道,且这个渠道有一个距离,这样就形
成了一个有向完全图。 。 世界末日的预兆已经来了 , 世界上很多东西都在遭到不
明原因的破坏,包括这些通信渠道。现在为了联合制造出诺亚方舟,需要统计
所有国家对 (a到b和b到a是不同的 ) 之间通信最短距离之和 。( ( 例如只有两个星
球 ,a到b与b 到a的距离都是1, 则最短距离和为2。) ) 可是每隔一段时间就有一些
渠道会被破坏,现在 24 星球的首领 大龙 急需要你来解决这个问题。
【输入文件】
读入文件 destroy.in
对于每组数据 , 第一行是一个n, 表示有n个国家 , 接下来有n行 , 每有n 个 非
负 整数。第i行第j 列的数字表示国家i i 到国家j j 的通信渠道距离(距离不大于
10000 ) 。 接下来是一个数字m, 表示在可以预知的未来中会有m次破坏会施加到
通信渠道中 , 每次破坏只能破坏一条渠道 , 一条渠道可以被破坏多次, , 但是第
一次破坏这条渠道就无法再发送信息 。 接下来有m行 , 每行两个整数a、b, 表示
国家a到国家b的通信渠道遭到破坏。
【输出文件】
输出文件 destroy.out
对于每组数据 , 输出m m 行 , 第i i 行表示第i i 次破坏后对应的答案是多少 。 如果
存在两个国家无法相互到达,输出1 1 NF 。
【输入样例】
3
0 1 1
1 0 1
1 1 0
4 4
1 2
1 2
2 3
2 3
【输出样例】
7
7
8
1NF
【数据规模】
40% 的数据中 1<n<=50,1<m<=50;
100% 的数据中 1<n<=200,1<m<=200 。

————————————————————————————题解

删边有点麻烦,所以我们一次性读入m个询问,离线处理,把所有边删除,倒着加上一条条边,回溯状态

我们加上第m条边时,我们到达的就是m-1的状态,加上第m-1条边时,就是m-2询问的状态……加上第2条边时,就是1询问的状态

枚举i=1->n j=1->n 用一条边u,v更新g[i][j]=min(g[i][j],g[i][u]+val(u,v)+g[v][j]

同时因为边可能重复被删,用一个next数组记录这条边最早被删掉的时刻,样例中next[2]=1,如果next不为0,当前状态的边是无法复原的,所以直接由上一个时刻过继过来就可以了 

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <algorithm>
  5 #include <queue>
  6 #include <set>
  7 #include <vector>
  8 #include <string.h>
  9 #include <cmath>
 10 #define siji(i,x,y) for(int i=(x);i<=(y);++i)
 11 #define gongzi(j,x,y) for(int j=(x);j>=(y);--j)
 12 #define xiaosiji(i,x,y) for(int i=(x);i<(y);++i)
 13 #define sigongzi(j,x,y) for(int j=(x);j>(y);--j)
 14 #define inf 0x3f3f3f3f
 15 #define ivorysi
 16 #define mo 97797977
 17 #define hash 974711
 18 #define base 47
 19 #define MAXN 30005
 20 #define fi first
 21 #define se second
 22 #define pii pair<int,int>
 23 #define eps 1e-8
 24 typedef long long ll;
 25 using namespace std;
 26 int n,m;
 27 int f[205][205];
 28 int g[205][205];
 29 int a[205],b[205],ans[205],next[205];
 30 bool flag=0;
 31 void solve() {
 32     scanf("%d",&n);
 33     siji(i,1,n) {
 34         siji(j,1,n) {
 35             scanf("%d",&f[i][j]);
 36             g[i][j]=f[i][j];
 37         }
 38     }
 39     scanf("%d",&m);
 40     siji(i,1,m) {
 41         scanf("%d%d",&a[i],&b[i]);
 42         g[a[i]][b[i]]=-1;
 43     }
 44     siji(k,1,n) {
 45         siji(i,1,n) {
 46             siji(j,1,n) {
 47                 if(g[i][k]==-1 || g[k][j]==-1) continue;
 48                 int x=g[i][k]+g[k][j];
 49                 if(g[i][j]==-1) {
 50                     g[i][j]=x;
 51                 }
 52                 else {
 53                     g[i][j]=min(x,g[i][j]);
 54                 }
 55             }
 56         }
 57     }
 58     siji(i,1,m) {
 59         siji(j,i+1,m) {//这里打错了一次变量名
 60             if(a[i]==a[j] && b[i]==b[j]) {
 61                 if(next[j]==0) next[j]=i;
 62                 else if(next[j] > i) next[j]=i;
 63             }
 64         }
 65     }
 66     siji(i,1,n) {
 67         siji(j,1,n) {
 68             if(g[i][j]==-1) {ans[m]=-1;goto s;}
 69             ans[m]+=g[i][j];
 70         }
 71     }
 72     s:
 73     gongzi(i,m,2) {
 74         if(next[i]!=0) {ans[i-1]=ans[i];continue;}
 75         /*
 76         更新时不要直接g[a[i]][b[i]]=f[a[i]][b[i]]
 77         因为g[a[i]][b[i]]可能小于f[a[i]][b[i]]
 78         这样会得到错解
 79         */
 80         siji(j,1,n) {
 81             siji(k,1,n) {
 82 
 83                 if(g[j][a[i]] == -1 || g[b[i]][k] == -1) continue;
 84                 int x=g[j][a[i]]+f[a[i]][b[i]]+g[b[i]][k];
 85                 if(g[j][k]==-1) {
 86                     g[j][k]=x;
 87                 }
 88                 else {
 89                     g[j][k]=min(g[j][k],x);
 90                 }
 91             }
 92         }
 93         siji(j,1,n) {
 94             siji(k,1,n) {
 95                 if(g[j][k]==-1) {ans[i-1]=-1;goto t;}
 96                 ans[i-1]+=g[j][k];
 97             }
 98         }
 99         t:;
100     }
101     siji(i,1,m) {
102         if(ans[i]==-1) puts("1NF");
103         else {
104             printf("%d\n",ans[i]);
105         }
106     }
107 }
108 int main(int argc, char const *argv[])
109 {
110 #ifdef ivorysi
111     freopen("destroy.in","r",stdin);
112     freopen("destroy.out","w",stdout);
113 #else
114     freopen("f1.in","r",stdin);
115 #endif
116     solve();    
117     return 0;
118 }

 

posted @ 2017-02-07 18:58  sigongzi  阅读(262)  评论(0编辑  收藏  举报