[HNOI2007]紧急疏散evacuate
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 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
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 }