zoukankan      html  css  js  c++  java
  • bzoj 1189 [HNOI2007]紧急疏散evacuate 二分+网络流

    [HNOI2007]紧急疏散evacuate

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 3626  Solved: 1059
    [Submit][Status][Discuss]

    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

    题解:二分+二分图匹配吧,网络流可以,需要注意一下,一个时刻只能允许出去一个人,所以出口再裂几个点即可。

      1 #include<cstdio>
      2 const int M=4000000,inf=0x3f3f3f3f;
      3 int h[M],q[M],S,T;
      4 int es[M],enx[M],ev[M],e0[M],ep=2;
      5 int n,m;
      6 char s[64][64];
      7 bool bfs(){
      8     int ql=0,qr=0;
      9     for(int i=1;i<=T;i++)h[i]=0;
     10     h[S]=1;
     11     q[qr++]=S;
     12     while(ql!=qr){
     13         int w=q[ql++];
     14         for(int i=e0[w];i;i=enx[i]){
     15             if(!ev[i])continue;
     16             int u=es[i];
     17             if(h[u])continue;
     18             h[u]=h[w]+1;
     19             q[qr++]=u;
     20         }
     21     }
     22     return h[T];
     23 }
     24 int dfs(int w,int f){
     25     if(w==T)return f;
     26     int used=0,c;
     27     for(int i=e0[w];i;i=enx[i]){
     28         if(!ev[i])continue;
     29         int u=es[i];
     30         if(h[u]!=h[w]+1)continue;
     31         c=f-used;
     32         if(c>ev[i])c=ev[i];
     33         c=dfs(u,c);
     34         ev[i]-=c;
     35         ev[i^1]+=c;
     36         used+=c;
     37         if(f==used)return f;
     38     }
     39     if(f!=used)h[w]=0;
     40     return used;
     41 }
     42 void addedge(int a,int b,int f){
     43     es[ep]=b;enx[ep]=e0[a];ev[ep]=f;e0[a]=ep++;
     44     es[ep]=a;enx[ep]=e0[b];ev[ep]=0;e0[b]=ep++;
     45 }
     46 int xs[]={-1,0,1,0};
     47 int ys[]={0,-1,0,1};
     48 int qx[10000],qy[10000],tag[64][64],len[64][64],now=0;
     49 bool chk(int X){
     50     int pc=0;
     51     S=(n+2)*m+2+X*n*m;T=S+1;
     52     for(int i=0;i<=T;i++)e0[i]=0;ep=2;
     53     for(int i=1;i<=n;i++){
     54         for(int j=1;j<=m;j++){
     55             if(s[i][j]=='.')addedge(S,i*m+j,1),pc++;
     56             if(s[i][j]=='D'){
     57                 for(int c=0;c<=X;c++)addedge(i*m+j+c*n*m,T,1);
     58                 int ql=0,qr=0;
     59                 qx[0]=i;qy[0]=j;qr++;
     60                 ++now;
     61                 tag[i][j]=now;
     62                 len[i][j]=0;
     63                 while(ql<qr){
     64                     int x=qx[ql],y=qy[ql];ql++;
     65                     if(s[x][y]=='.'&&len[x][y]<=X)for(int c=len[x][y];c<=X;c++)addedge(x*m+y,i*m+j+c*n*m,1);
     66                     if(len[x][y]<=X)
     67                     for(int a=0;a<4;a++){
     68                         int x1=x+xs[a],y1=y+ys[a];
     69                         if((s[x1][y1]=='.')&&tag[x1][y1]!=now){
     70                             tag[x1][y1]=now;
     71                             len[x1][y1]=len[x][y]+1;
     72                             qx[qr]=x1;qy[qr]=y1;qr++;
     73                         }
     74                     }
     75                 }
     76             }
     77         }
     78     }
     79     while(bfs())pc-=dfs(S,inf);
     80     return !pc;
     81 }
     82 int main(){
     83     scanf("%d%d",&n,&m);
     84     for(int i=0;i<=51;i++)for(int j=0;j<=51;j++)s[i][j]='X';
     85     for(int i=1;i<=n;i++){
     86         scanf("%s",s[i]+1);
     87         s[i][m+1]='X';
     88     }
     89     int L=0,R=n*m+1,M;
     90     while(L<R){
     91         M=L+R>>1;
     92         if(chk(M))R=M;
     93         else L=M+1;
     94     }
     95     while(!chk(L)&&L<=n*m)++L;
     96     while(L>0&&chk(L-1))--L;
     97     if(L<=n*m)printf("%d
    ",L);
     98     else puts("impossible");
     99     return 0;
    100 }
  • 相关阅读:
    杭州西郊千湖岛-天下第一秀水
    windows phone7 豆瓣FM
    wp7 中 HubTile控件自定义大小。
    wp7 HubTile
    Windows Phone 7之XNA游戏:重力感应
    WP7:模拟开始屏幕Tile漂动效果
    windows 8 项目
    手把手教你 用 wpf 制作metro ProgressRing (Windows8 等待动画)
    windows8 开发教程 教你制作 多点触控Helper可将任意容器内任意对象进行多点缩放
    仿windows8 开始菜单 实现HubTileBase 以及仿鲜果联播实现 PulsingTile(脉冲磁贴)
  • 原文地址:https://www.cnblogs.com/fengzhiyuan/p/8835007.html
Copyright © 2011-2022 走看看