zoukankan      html  css  js  c++  java
  • 抢救实验数据

    题目背景

    某大型实验中心的一个实验室发生了毒气泄露,现在实验员想要抢救实验数据。

    题目描述

    实验中心可以看做一个 nn 个点 mm 条边的无向联通图。
    所有实验员每秒可以走到一个相邻的实验室并收集其中的数据,毒气每秒会蔓延到所有的相邻实验室。 当一个实验员回到了大厅 s,我们称他抢救了数据。
    实验员不能进入有毒气的实验室(如果他和毒气在同一秒进入实验室也不行)。
    大厅周围有严格的保护措施,不会被毒气蔓延。(具体可以参考样例二)
    现在所有实验员都在大厅 s,毒气泄露的实验室为点 t。假如有足够多的实验员同时出发,请问最多能抢救多少个实验室的数据?

    输入格式

    第一行两个正整数 n,m,表示实验中心的点数和边数。
    第二至 m+1 行每行两个正整数 u,v,代表 u,v实验室之间有一条边。
    第 m+2行两个正整数 s,t,表示大厅和毒气泄露点。

    输出格式

    一行一个整数,表示最多能抢救多少个的实验室的数据。

    输入输出样例

    输入 #1

    4 3
    1 2
    2 3
    3 4
    1 4
    

    输出 #1

    1
    

    输入 #2

    6 7
    1 2
    2 3
    3 1
    4 5
    5 6
    6 4
    1 4
    1 4
    

    输出 #2

    2
    

    输入 #3

    15 14
    1 2
    2 3
    3 4
    4 5
    5 6
    6 7
    7 8
    8 9
    9 10
    3 11
    11 12
    12 13
    13 14
    14 15
    1 10
    

    输出 #3

    6
    

    说明/提示

    请注意常数因子带来的程序效率上的影响。

    【样例解释一】
    只有 2 号实验室可以到达并回来。

    【样例解释二】
    因为大厅是坚不可摧的,所以 5,6 两个实验室会被毒气蔓延到,而 2,3 两个实验室永远不会被蔓延到。

    【样例解释三】
    可以被抢救的点为:2,3,4,5,11,12。

    【数据范围】
    本题采用捆绑测试
    (对于 10\% 的数据,2 leq n,m leq 20)
    (对于 30\% 的数据,2 leq n leq 2000,1 leq m leq 10000)
    (对于 70\% 的数据,2 leq n leq 2 imes 10^5)
    (对于 100\% 的数据,2 leq n,m leq 5 imes 10^6)

    题目解析

    首先是求出每个节点能够成功返回(S)的最晚到达时间(deadLine),通过最短路径算法,求出毒气到达每个节点的最短时间,作为初始的(deadLine)

    然后是从(S)点的临近节点开始,更新(deadLine)。求出每个节点最小的截止时间

    因为从(S)临近节点开始,随着更新过程的推进,队列中各个节点的(deadLine)单调不减。又因为(n)的最大值(5*10^6),使用优先队列BFS更新(O(nlogn))效率不够。所以考虑直接用以(deadLine)值为下标的vector代替有限队列,更新时枚举(deadLine)值从小到大更新vector,从而实现(O(n+m))复杂度

    最后是求出(S)到达各个节点的最短路径,判断是否能在截止时间前到达该节点

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include<queue>
    #include<vector>
    using namespace std;
    char gc() {
      static char now[1 << 20], *S, *T;
      if (T == S) {
        T = (S = now) + std::fread(now, 1, 1 << 20, stdin);
        if (T == S) return EOF;
      }
      return *S++;
    }
    template <typename T>
    void Read(T &x) {
      x = 0;
      char c = gc();
      while (c < '0' || c > '9') c = gc();
      x = c - '0';
      while ((c = gc()) >= '0' && c <= '9') x = x * 10 + c - '0';
    }
    template <typename T, typename... Args>
    void Read(T &x, Args &... args) {
      Read(x);
      Read(args...);
    }
    
    struct Edge{
      int next,to;
    }edge[10000005];
    int head[5000005],num=0;
    int n,m,vis[5000005],S,T,deadline[5000005],dis[5000005];
    int q[10000005],h,t,Max;
    vector<int> vec[5000005];
    void add(int u,int v){
      num++;
      edge[num].next=head[u];
      head[u]=num;
      edge[num].to=v;
    }
    void getDis(){
        memset(dis,127/2,sizeof(dis));
        memset(vis,0,sizeof(vis));
        dis[S]=0;
        h=0,t=1;
        q[h]=S;
        vis[S]=1;
        while (h<t){
          int u=q[h++];
          for (int i=head[u];i;i=edge[i].next){
            int v=edge[i].to;
            if (vis[v]) continue;
            dis[v]=dis[u]+1;
            q[t++]=v;
            vis[v]=1;
          }
        }
    }
    void getDeadLine(){
        memset(deadline,127/2,sizeof(deadline));
        Max=deadline[0];
        memset(vis,0,sizeof(vis));
        deadline[T]=0;
        h=0,t=1;
        q[h]=T;
        vis[T]=1;
        while (h<t){
          int u=q[h++];
          for (int i=head[u];i;i=edge[i].next){
            int v=edge[i].to;
            if (vis[v]||v==S) continue;
            deadline[v]=deadline[u]+1;
            q[t++]=v;
            vis[v]=1;
          }
        }
    }
    void calDeadLine(){
      memset(vis,0,sizeof(vis));
      int maxdead=0;
      vis[S]=1;
      for (int i=head[S];i;i=edge[i].next){
          int v=edge[i].to;
          if (deadline[v]==Max) continue;
          vec[deadline[v]].push_back(v);
          maxdead=(maxdead<deadline[v])?deadline[v]:maxdead;
          vis[v]=1;
      } 
      for (int i=maxdead;i;i--){
        for (int j=0;j<vec[i].size();j++){
          int u=vec[i][j];
          for (int k=head[u];k;k=edge[k].next){
            int v=edge[k].to;
            if (vis[v]) continue;
            deadline[v]=(deadline[v]<deadline[u]-1)?deadline[v]:deadline[u]-1;
            vis[v]=1;
            vec[deadline[v]].push_back(v);
          }
        }
      }
    }
    int main(){
      int u,v;
        Read(n,m);
        for (int i=0;i<m;i++){
          Read(u,v);
          add(u,v);add(v,u);
        }
        Read(S,T);
        getDis();
        //cout<<"getDis"<<endl;
        getDeadLine();
        //cout<<"getDeadLine"<<endl;
        calDeadLine();
        //cout<<"calDeadLine"<<endl;
        int ans=0;
        for (int i=1;i<=n;i++){
          //cout<<deadline[i]<<endl;
          if (i!=S&&dis[i]<deadline[i]&&(vis[i]||deadline[i]==Max)) ans++;
        }
        cout<<ans<<endl;
    }
    
  • 相关阅读:
    python第三天
    python第二天
    python第一天
    Linux之VIM常用功能
    Linux输入输出管理
    Linux文件操作及管理
    Linux虚拟机基本操作
    JAVA堆,栈的区别,用AarrayList、LinkedList自定义栈
    mysql优化limit
    MySql五大引擎的区别以及优劣之分
  • 原文地址:https://www.cnblogs.com/Y-E-T-I/p/15130219.html
Copyright © 2011-2022 走看看