zoukankan      html  css  js  c++  java
  • 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
    ",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 }
  • 相关阅读:
    JavaScript你所不知道的困惑(3)
    Android的代码都得自己一个个敲一遍吗?
    现代化农业在美国的兴起与发展
    高内聚与低耦合实现小记
    iOS 载入图片选择imageNamed 方法还是 imageWithContentsOfFile?
    swift笔记——环境搭建及Hello,Swift!
    HDU 4832(DP+计数问题)
    [TJOI2019]甲苯先生的线段树
    2019-8-31-C#-如何写-DEBUG-输出
    2019-8-31-C#-如何写-DEBUG-输出
  • 原文地址:https://www.cnblogs.com/ivorysi/p/6375556.html
Copyright © 2011-2022 走看看