zoukankan      html  css  js  c++  java
  • bzoj1189 [HNOI2007]紧急疏散

    Description

    发生了火警,所有人员需要紧急疏散!假设每个房间是一个N M的矩形区域。每个格子如果是'.',那么表示这是一块空地;如果是'X',那么表示这是一面墙,如果是'D',那么表示这是一扇门,人们可以从这儿撤出房间。已知门一定在房间的边界上,并且边界上不会有空地。最初,每块空地上都有一个人,在疏散的时候,每一秒钟每个人都可以向上下左右四个方向移动一格,当然他也可以站着不动。疏散开始后,每块空地上就没有人数限制了(也就是说每块空地可以同时站无数个人)。但是,由于门很窄,每一秒钟只能有一个人移动到门的位置,一旦移动到门的位置,就表示他已经安全撤离了。现在的问题是:如果希望所有的人安全撤离,最短需要多少时间?或者告知根本不可能。

    Input

    输入文件第一行是由空格隔开的一对正整数N与M,3<=N <=20,3<=M<=20,以下N行M列描述一个N M的矩阵。其中的元素可为字符'.'、'X'和'D',且字符间无空格。

    Output

    只有一个整数K,表示让所有人安全撤离的最短时间,如果不可能撤离,那么输出'impossible'(不包括引号)。

    Sample Input

    5 5
    XXXXX
    X...D
    XX.XX
    X..XX
    XXDXX

    Sample Output

    3

    HINT 

    2015.1.12新加数据一组,鸣谢1756500824

    C++语言请用scanf("%s",s)读入!

    正解:最大流。

    比较经典的按时间拆点的最大流套路。首先预处理出每个空地到每个门需要的距离,然后把所有门按照时间拆点。如果空地到这个点的时刻为$t$,那么则把空点向这个点时刻$t$对应的点连边,同时每个门的前一时间向后一时间连流量为$inf$的边,使得空地也可以使用后面的时间对应的点,其他流量都为$1$。我们可以从小到大枚举时间,然后把当前时间的点和边加入图中,跑残量网络就行了,当满流时就输出当前时间。无解情况很好判断,只要一个空地不能到达所有的门,那么就无解了。

      1 //It is made by wfj_2048~
      2 #include <algorithm>
      3 #include <iostream>
      4 #include <cstring>
      5 #include <cstdlib>
      6 #include <cstdio>
      7 #include <vector>
      8 #include <cmath>
      9 #include <queue>
     10 #include <stack>
     11 #include <map>
     12 #include <set>
     13 #define inf (1061109567)
     14 #define N (3000010)
     15 #define il inline
     16 #define RG register
     17 #define ll long long
     18 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
     19 
     20 using namespace std;
     21 
     22 struct edge{ int nt,to,flow,cap; }g[N];
     23 
     24 int qx[510],qy[510],dep[510],a[22][22],b[22][22],vis[22][22],dis[510][510];
     25 int head[N],cur[N],d[N],q[N],S,T,n,m,num,cnt,cnt1,cnt2,flow;
     26 char s[22][22];
     27 
     28 const int d1[4]={1,0,-1,0};
     29 const int d2[4]={0,1,0,-1};
     30 
     31 il int gi(){
     32     RG int x=0,q=1; RG char ch=getchar();
     33     while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
     34     if (ch=='-') q=-1,ch=getchar();
     35     while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar();
     36     return q*x;
     37 }
     38 
     39 il void insert(RG int from,RG int to,RG int cap){
     40     g[++num]=(edge){head[from],to,0,cap},head[from]=num; return;
     41 }
     42 
     43 il int bfs(RG int S,RG int T){
     44     memset(d,0,sizeof(d)),d[S]=1;
     45     RG int h=0,t=1; q[t]=S;
     46     while (h<t){
     47     RG int x=q[++h],v;
     48     for (RG int i=head[x];i;i=g[i].nt){
     49         v=g[i].to;
     50         if (!d[v] && g[i].cap>g[i].flow){
     51         d[v]=d[x]+1,q[++t]=v;
     52         if (v==T) return 1;
     53         }
     54     }
     55     }
     56     return 0;
     57 }
     58 
     59 il int dfs(RG int x,RG int T,RG int a){
     60     if (!a || x==T) return a; RG int flow=0,f,v;
     61     for (RG int &i=cur[x];i;i=g[i].nt){
     62     v=g[i].to;
     63     if (d[v]==d[x]+1 && g[i].cap>g[i].flow){
     64         f=dfs(v,T,min(a,g[i].cap-g[i].flow));
     65         if (!f){ d[v]=0; continue; }
     66         g[i].flow+=f,g[i^1].flow-=f;
     67         flow+=f,a-=f; if (!a) return flow;
     68     }
     69     }
     70     return flow;
     71 }
     72 
     73 il int maxflow(RG int S,RG int T){
     74     RG int flow=0;
     75     while (bfs(S,T)){
     76     memcpy(cur,head,sizeof(head));
     77     flow+=dfs(S,T,inf);
     78     }
     79     return flow;
     80 }
     81 
     82 il void spfa(RG int id,RG int x,RG int y){
     83     memset(vis,0,sizeof(vis)),vis[x][y]=1;
     84     RG int h=0,t=1; qx[t]=x,qy[t]=y,dep[t]=0;
     85     while (h<t){
     86     x=qx[++h],y=qy[h]; RG int X,Y;
     87     for (RG int i=0;i<4;++i){
     88         X=x+d1[i],Y=y+d2[i];
     89         if (X<=0 || X>n || Y<=0 || Y>m) continue;
     90         if (vis[X][Y] || s[X][Y]=='X') continue;
     91         if (b[X][Y]) dis[id][b[X][Y]]=dep[h]+1;
     92         else vis[X][Y]=1,qx[++t]=X,qy[t]=Y,dep[t]=dep[h]+1;
     93     }
     94     }
     95     return;
     96 }
     97 
     98 il void work(){
     99     n=gi(),m=gi(),num=1,memset(dis,0x3f3f3f,sizeof(dis));
    100     for (RG int i=1;i<=n;++i){
    101     scanf("%s",s[i]+1);
    102     for (RG int j=1;j<=m;++j){
    103         if (s[i][j]=='.') a[i][j]=++cnt1;
    104         if (s[i][j]=='D') b[i][j]=++cnt2;
    105     }
    106     }
    107     for (RG int i=1;i<=n;++i)
    108     for (RG int j=1;j<=m;++j) if (a[i][j]) spfa(a[i][j],i,j);
    109     for (RG int i=1,fg;i<=cnt1;++i){
    110     fg=0;
    111     for (RG int j=1;j<=cnt2;++j)
    112         if (dis[i][j]<inf){ fg=1; break; }
    113     if (!fg){ puts("impossible"); return; }
    114     }
    115     cnt=cnt1,S=++cnt,T=++cnt;
    116     for (RG int i=1;i<=cnt1;++i) insert(S,i,1),insert(i,S,0);
    117     for (RG int i=1;i<=cnt2;++i) insert(++cnt,T,1),insert(T,cnt,0);
    118     for (RG int i=1;i<=cnt1;++i)
    119     for (RG int j=1;j<=cnt2;++j)
    120         if (dis[i][j]==1) insert(i,cnt-cnt2+j,1),insert(cnt-cnt2+j,i,0);
    121     if ((flow=maxflow(S,T))==cnt1){ puts("1"); return; }
    122     for (RG int ans=2;;++ans){
    123     for (RG int i=1;i<=cnt2;++i){
    124         insert(++cnt,T,1),insert(T,cnt,0);
    125         insert(cnt-cnt2,cnt,inf),insert(cnt,cnt-cnt2,0);
    126     }
    127     for (RG int i=1;i<=cnt1;++i)
    128         for (RG int j=1;j<=cnt2;++j)
    129         if (dis[i][j]==ans) insert(i,cnt-cnt2+j,1),insert(cnt-cnt2+j,i,0);
    130     if ((flow+=maxflow(S,T))==cnt1){ printf("%d
    ",ans); return; }
    131     }
    132     return;
    133 }
    134 
    135 int main(){
    136     File("evacuate");
    137     work();
    138     return 0;
    139 }
  • 相关阅读:
    初识Django-前后端不分离(一)
    虚拟环境的搭建
    python+request+Excel做接口自动化测试(二)
    使用postman+newman+python做接口自动化测试
    如何处理接口响应结果分析
    request使用的封装
    python中unittest的使用
    使用python的接口测试环境搭建及使用
    关于测试流程的指导心得
    Redis 学习
  • 原文地址:https://www.cnblogs.com/wfj2048/p/7214017.html
Copyright © 2011-2022 走看看