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\n",ans); return; }
131     }
132     return;
133 }
134 
135 int main(){
136     File("evacuate");
137     work();
138     return 0;
139 }

 

posted @ 2017-07-20 19:44  wfj_2048  阅读(180)  评论(0编辑  收藏  举报