【BZOJ 1189】[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
XXXXX
X...D
XX.XX
X..XX
XXDXX
Sample Output
3
HINT
2015.1.12新加数据一组,鸣谢1756500824
C++语言请用scanf("%s",s)读入!
BFS处理出人到门的距离
二分答案,判断是否可以建边,S指向每一块空地,空地到门如果可以建边就建一条容量为x的边
每个门按照时间拆点,保证单位时间内走一次,然后跑最大流
代码太丑。。。
1 #include<cstdio> 2 #include<cstring> 3 #include<cmath> 4 #include<iostream> 5 using namespace std; 6 const int inf=100000000,N=161000; 7 struct ee{int to,next,f;}e[5000001]; 8 struct bb{int x,y;}b[1010]; 9 int head[N],q[N*2],dis[N],dis1[410][21][21],map[21][21]; 10 int S,T,n,m,cnt=1,ans1,w,ans,door=1,num; 11 char s[30]; 12 int fx[4]={0,0,1,-1},fy[4]={1,-1,0,0}; 13 void ins(int u,int v,int f){ 14 e[++cnt].to=v;e[cnt].f=f;e[cnt].next=head[u];head[u]=cnt; 15 e[++cnt].to=u;e[cnt].f=0;e[cnt].next=head[v];head[v]=cnt; 16 } 17 18 bool bfs(){ 19 for (int i=1;i<=T;i++) dis[i]=inf; 20 int h=0,t=1,now; 21 q[1]=S;dis[S]=0; 22 while(h!=t){ 23 now=q[++h]; 24 for (int i=head[now];i;i=e[i].next){ 25 int v=e[i].to; 26 if (e[i].f&&dis[now]+1<dis[v]){ 27 dis[v]=dis[now]+1; 28 if (v==T)return 1; 29 q[++t]=v; 30 } 31 } 32 } 33 if (dis[T]==inf) return 0; return 1; 34 } 35 36 int dinic(int now,int f){ 37 if (now==T) return f; 38 int rest=f; 39 for (int i=head[now];i;i=e[i].next){ 40 int v=e[i].to; 41 if (e[i].f&&dis[v]==dis[now]+1&&rest){ 42 int t=dinic(v,min(rest,e[i].f)); 43 if (!t) dis[v]=0; 44 e[i].f-=t; 45 e[i^1].f+=t; 46 rest-=t; 47 //if(t) printf("%d %d %d\n",now,v,e[i].f); 48 } 49 } 50 return f-rest; 51 } 52 void bfs1(int k,int x1,int y1){ 53 int h,t;h=t=0; 54 b[++t].x=x1,b[t].y=y1;dis1[k][x1][y1]=0; 55 while(h<t){ 56 int x=b[++h].x,y=b[h].y; 57 for(int i=0;i<4;i++){ 58 int nx=x+fx[i],ny=y+fy[i]; 59 if(map[nx][ny]==1&&dis1[k][nx][ny]>dis1[k][x][y]+1){ 60 dis1[k][nx][ny]=dis1[k][x][y]+1; 61 b[++t].x=x+fx[i],b[t].y=y+fy[i]; 62 } 63 } 64 } 65 } 66 67 void build(int x){ 68 memset(head,0,sizeof(head)); 69 memset(e,0,sizeof(e)); 70 for(int i=1;i<=n;i++) 71 for(int j=1;j<=m;j++){ 72 if (map[i][j]==1) { 73 int u=(i-1)*m+j; 74 ins(S,u,1); 75 for(int k=2;k<=door;k++) 76 if(dis1[k][i][j]<=x) ins(u,dis1[k][i][j]+(k-2)*x+m*n,x); 77 } 78 if(map[i][j]>1){ 79 for(int k=1;k<=x;k++){ 80 int u=((map[i][j]-2)*x+k)+m*n; 81 if(k!=x)ins(u,u+1,x-k+1); 82 ins(u,T,1); 83 } 84 } 85 } 86 } 87 88 bool judge(int x){ 89 build(x); 90 ans=0; 91 while(bfs()) 92 ans+=dinic(S,inf); 93 if(ans>=num) return 1; 94 return 0; 95 96 } 97 int main(){ 98 scanf("%d%d",&n,&m); 99 S=0,T=160010; 100 for(int i=1;i<=n;i++){ 101 scanf("%s",s+1); 102 for(int j=1;j<=m;j++) { 103 if (s[j]=='.')map[i][j]=1,num++; 104 else if(s[j]=='D') map[i][j]=++door; 105 } 106 } 107 for(int i=2;i<=door;i++) 108 for(int j=1;j<=n;j++) 109 for(int k=1;k<=m;k++) dis1[i][j][k]=inf; 110 for(int j=1;j<=n;j++) 111 for(int k=1;k<=m;k++) 112 if(map[j][k]>1) bfs1(map[j][k],j,k); 113 int l=0,r=400; 114 ans1=-1; 115 while(l<=r){ 116 int mid=(l+r)>>1; 117 if(judge(mid)) ans1=mid,r=mid-1; 118 else l=mid+1; 119 } 120 if(ans1==-1) printf("impossible"); 121 else printf("%d",ans1); 122 }