• 【BZOJ 1189】[HNOI2007]紧急疏散evacuate


    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)读入!

     
    BFS处理出人到门的距离
    二分答案,判断是否可以建边,S指向每一块空地,空地到门如果可以建边就建一条容量为x的边
    每个门按照时间拆点,保证单位时间内走一次,然后跑最大流
    代码太丑。。。
      1 #include<cstdio>
      2 #include<cstring>
      3 #include<cmath>
      4 #include<iostream>
      5 using namespace std;
      6 const int inf=100000000,N=161000;
      7 struct ee{int to,next,f;}e[5000001];
      8 struct bb{int x,y;}b[1010];
      9 int head[N],q[N*2],dis[N],dis1[410][21][21],map[21][21];
     10 int S,T,n,m,cnt=1,ans1,w,ans,door=1,num;
     11 char s[30];
     12 int fx[4]={0,0,1,-1},fy[4]={1,-1,0,0}; 
     13 void ins(int u,int v,int f){
     14     e[++cnt].to=v;e[cnt].f=f;e[cnt].next=head[u];head[u]=cnt;
     15     e[++cnt].to=u;e[cnt].f=0;e[cnt].next=head[v];head[v]=cnt;
     16 }
     17   
     18 bool bfs(){
     19     for (int i=1;i<=T;i++) dis[i]=inf;
     20     int h=0,t=1,now;
     21     q[1]=S;dis[S]=0;
     22     while(h!=t){
     23         now=q[++h];
     24         for (int i=head[now];i;i=e[i].next){
     25             int v=e[i].to;
     26             if (e[i].f&&dis[now]+1<dis[v]){
     27                 dis[v]=dis[now]+1;
     28                 if (v==T)return 1;
     29                 q[++t]=v;
     30             }
     31         }
     32     }
     33     if (dis[T]==inf) return 0; return 1;
     34 }
     35   
     36 int dinic(int now,int f){
     37     if (now==T) return f;
     38     int rest=f;
     39     for (int i=head[now];i;i=e[i].next){
     40         int v=e[i].to;
     41         if (e[i].f&&dis[v]==dis[now]+1&&rest){
     42             int t=dinic(v,min(rest,e[i].f));
     43             if (!t) dis[v]=0;
     44             e[i].f-=t;
     45             e[i^1].f+=t;
     46             rest-=t;
     47             //if(t) printf("%d %d %d
    ",now,v,e[i].f);
     48         }
     49     }
     50     return f-rest;
     51 }
     52 void bfs1(int k,int x1,int y1){
     53     int h,t;h=t=0;
     54     b[++t].x=x1,b[t].y=y1;dis1[k][x1][y1]=0;
     55     while(h<t){
     56         int x=b[++h].x,y=b[h].y;
     57         for(int i=0;i<4;i++){
     58             int nx=x+fx[i],ny=y+fy[i];
     59             if(map[nx][ny]==1&&dis1[k][nx][ny]>dis1[k][x][y]+1){
     60                 dis1[k][nx][ny]=dis1[k][x][y]+1;
     61                 b[++t].x=x+fx[i],b[t].y=y+fy[i];
     62             }
     63         }
     64     }
     65 }
     66   
     67 void build(int x){
     68     memset(head,0,sizeof(head));
     69     memset(e,0,sizeof(e));
     70     for(int i=1;i<=n;i++)
     71         for(int j=1;j<=m;j++){
     72             if (map[i][j]==1) {
     73                 int u=(i-1)*m+j;
     74                 ins(S,u,1);
     75                 for(int k=2;k<=door;k++)
     76                     if(dis1[k][i][j]<=x) ins(u,dis1[k][i][j]+(k-2)*x+m*n,x);
     77             }
     78             if(map[i][j]>1){
     79                 for(int k=1;k<=x;k++){
     80                     int u=((map[i][j]-2)*x+k)+m*n;
     81                     if(k!=x)ins(u,u+1,x-k+1);
     82                     ins(u,T,1);
     83                 }
     84             }
     85         }
     86 } 
     87   
     88 bool judge(int x){
     89     build(x);
     90     ans=0;
     91     while(bfs()) 
     92     ans+=dinic(S,inf);
     93     if(ans>=num) return 1;
     94     return 0;
     95          
     96 }  
     97 int main(){
     98     scanf("%d%d",&n,&m);
     99     S=0,T=160010;
    100     for(int i=1;i<=n;i++){
    101             scanf("%s",s+1);
    102             for(int j=1;j<=m;j++) {
    103                 if (s[j]=='.')map[i][j]=1,num++;
    104                 else if(s[j]=='D') map[i][j]=++door;
    105             }
    106         }
    107     for(int i=2;i<=door;i++)
    108         for(int j=1;j<=n;j++)
    109             for(int k=1;k<=m;k++) dis1[i][j][k]=inf; 
    110         for(int j=1;j<=n;j++)
    111             for(int k=1;k<=m;k++) 
    112                 if(map[j][k]>1) bfs1(map[j][k],j,k);
    113     int l=0,r=400;
    114     ans1=-1;
    115     while(l<=r){
    116         int mid=(l+r)>>1;
    117         if(judge(mid)) ans1=mid,r=mid-1;
    118         else l=mid+1;
    119     }
    120     if(ans1==-1) printf("impossible");
    121     else printf("%d",ans1);
    122 } 
  • 相关阅读:
    【luogu P4139】 上帝与集合的正确用法
    pb_ds学习
    【luogu P3868】 [TJOI2009]猜数字
    BZOJ3040: 最短路(road)
    【luogu P1064】 金明的预算方案
    【luogu P2893】 [USACO08FEB]修路Making the Grade
    【luogu P2801】 教主的魔法
    UVA10816 Travel in Desert
    P2916 [USACO08NOV]安慰奶牛Cheering up the Cow
    【BZOJ 2054】 疯狂的馒头
  • 原文地址:https://www.cnblogs.com/wuminyan/p/5205062.html
Copyright © 2020-2023  润新知