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 }
  • 相关阅读:
    73. Set Matrix Zeroes
    289. Game of Live
    212. Word Search II
    79. Word Search
    142. Linked List Cycle II
    141. Linked List Cycle
    287. Find the Duplicate Number
    260. Single Number III
    137. Single Number II
    Oracle EBS中有关Form的触发器的执行顺序
  • 原文地址:https://www.cnblogs.com/wfj2048/p/7214017.html
Copyright © 2011-2022 走看看