您的位置:首页 > 其它

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

2017-02-07 18:58 169 查看

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 }

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: