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)读入!
正解:最大流。
比较经典的按时间拆点的最大流套路。首先预处理出每个空地到每个门需要的距离,然后把所有门按照时间拆点。如果空地到这个点的时刻为$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 }