zoukankan      html  css  js  c++  java
  • bzoj1189: [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)读入!

    题解:

    先由S向每个有人的点连一条容量为1的边,然后二分时间t,对于每个每个门拆成t个点,每个点向T和下一个时间的点分别连容量为1和inf的边,表示这个门可以在每个时间里出来一个人,多余的人等到下一个时间

    ps:网上的题解大多都是错的,反例去见黄学长博客里的评论

    code:

      1 #include<cstdio>
      2 #include<iostream>
      3 #include<cmath>
      4 #include<cassert>
      5 #include<cstring>
      6 #include<algorithm>
      7 #define maxn 160000
      8 #define maxm 400000
      9 #define inf 1061109567
     10 using namespace std;
     11 char ch;
     12 bool ok;
     13 void read(int &x){
     14     for (ok=0,ch=getchar();!isdigit(ch);ch=getchar()) if (ch=='-') ok=1;
     15     for (x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar());
     16     if (ok) x=-x;
     17 }
     18 char graph[22][22];
     19 int n,m,cnt,pos[22][22],l,r,mid;
     20 struct flow{
     21     int s,t,idx,tot,now[maxn],son[maxm],pre[maxm],val[maxm];
     22     int dis[maxn],head,tail,list[maxn];
     23     bool bo[maxn];
     24     void init(){s=0,t=1,idx=1,tot=1,memset(now,0,sizeof(now));}
     25     void put(int a,int b,int c){pre[++tot]=now[a],now[a]=tot,son[tot]=b,val[tot]=c;}
     26     void add(int a,int b,int c){put(a,b,c),put(b,a,0);}
     27     bool bfs(){
     28         memset(bo,0,sizeof(bo));
     29         head=0,tail=1,list[1]=s,bo[s]=1,dis[s]=0;
     30         while (head<tail){
     31             int u=list[++head];
     32             for (int p=now[u],v=son[p];p;p=pre[p],v=son[p])
     33                 if (val[p]&&!bo[v]) bo[v]=1,dis[v]=dis[u]+1,list[++tail]=v;
     34         }
     35         return bo[t];
     36     }
     37     int dfs(int u,int rest){
     38         if (u==t) return rest;
     39         int ans=0;
     40         for (int p=now[u],v=son[p];p&&rest;p=pre[p],v=son[p])
     41             if (val[p]&&dis[v]==dis[u]+1){
     42                 int d=dfs(v,min(rest,val[p]));
     43                 val[p]-=d,val[p^1]+=d,ans+=d,rest-=d;
     44             }
     45         if (!ans) dis[u]=-1;
     46         return ans;
     47     }
     48     int dinic(){
     49         int ans=0;
     50         while (bfs()) ans+=dfs(s,inf);
     51         return ans;
     52     }
     53 }f,tmp;
     54 struct Point{
     55     int x,y,id;
     56 }list[405];
     57 int head,tail,g[405][405],dep[42][42];
     58 bool bo[42][42],flag;
     59 const int dx[4]={1,0,-1,0};
     60 const int dy[4]={0,1,0,-1};
     61 void bfs(int x,int y,int id){
     62     memset(bo,0,sizeof(bo));
     63     head=0,tail=1,list[1]=(Point){x,y,0},bo[x][y]=1,dep[x][y]=0;
     64     while (head<tail){
     65         Point p=list[++head];
     66         int d=dep[p.x][p.y];
     67         if (d) g[p.id][id]=d;
     68         for (int i=0;i<4;i++){
     69             int xx=p.x+dx[i],yy=p.y+dy[i];
     70             if (xx<=0||xx>n||yy<=0||yy>m||graph[xx][yy]!='.'||bo[xx][yy]) continue;
     71             list[++tail]=(Point){xx,yy,pos[xx][yy]},bo[xx][yy]=1,dep[xx][yy]=d+1;
     72         }
     73     }
     74 }
     75 bool check(int lim){
     76     f=tmp;
     77     for (int i=2;i<=f.idx;i++) for (int j=1;j<=cnt;j++) if (g[i][j]<=lim&&g[i][j])
     78         f.add(i,f.idx+cnt*(g[i][j]-1)+j,1);
     79     for (int i=1;i<=cnt;i++) for (int j=1;j<=lim;j++){
     80         f.add(f.idx+cnt*(j-1)+i,f.t,1);
     81         if (j!=lim) f.add(f.idx+cnt*(j-1)+i,f.idx+cnt*j+i,inf);
     82     }
     83     return f.dinic()==f.idx-1;
     84 }
     85 int main(){
     86     read(n),read(m),f.init();
     87     for (int i=1;i<=n;i++) scanf("%s",graph[i]+1);
     88     for (int i=1;i<=n;i++) for (int j=1;j<=m;j++)
     89         if (graph[i][j]=='.') pos[i][j]=++f.idx,f.add(f.s,f.idx,1);
     90         else if (graph[i][j]=='D') pos[i][j]=++cnt;
     91     for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) if (graph[i][j]=='D') bfs(i,j,pos[i][j]);
     92     for (int i=2;i<=f.idx;i++){
     93         bool fuck=1;
     94         for (int j=1;j<=cnt;j++) if (g[i][j]!=0) fuck=0;
     95         if (fuck){flag=1;break;}
     96     }
     97     if (flag){puts("impossible");return 0;}
     98     for (tmp=f,l=1,r=400,mid=(l+r)>>1;l<r;mid=(l+r)>>1) if (check(mid)) r=mid; else l=mid+1;
     99     printf("%d
    ",l);
    100     return 0;
    101 }
  • 相关阅读:
    iOS.UI_正则表达式(特殊字符)
    iOS.UI_正则(电话号码)
    iOS远程推送h获取Token
    CoreData教学完整版(封装我们自己的CoreData工具)_Dylan
    Swift基础加强_跟我打500行
    xmpp好友请求5
    XMPP教学小结1
    xmpp好友状态4
    XMPP好友列表3
    XMPP收发消息2
  • 原文地址:https://www.cnblogs.com/chenyushuo/p/5137756.html
Copyright © 2011-2022 走看看