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
解题思路:
考虑每个点到每个门的最短路一定所以先Bfs/Dijstra一遍得到每个点到每个门到最短距离。
考虑随着时间的推移,每个点能够到达的门也就越多,所以可以说是动态加边。
这时的正确方法是二分答案,建图网络流。
显然是源点连人,在时间允许的情况下人连门,容量为1。门连汇点,容量为T。
这样做理论上是很好的,但是有一个问题,那就是本题的特殊性,每个格子可以重复走人但是门只能一个一个出。
这就十分不和谐了,因为上面的做法并不能处理两个人同时到达的情况。
考虑一个问题,到底是什么性质没有被体现导致建图瑕疵。
这里可以认为门在T时刻关闭,那么本质上每个人都有一个剩余时间,假如说一起到然后一个一个出,
这里的问题就是假如说一起到的人比较多,假如说大于T那么一定不能全部出去。
所以需要有一个条件来限制每个人到达时还剩多少时间,换句话说,需要表现他究竟是什么时间到达的。
这样,将每个门拆成T个点,代表该时刻到达的门(相当于给门分层)。
每个点向到达时间的门连边,每层门向下一层连流量为$inf$的边。
跑最大流验证就好了。
代码:
1 #include<queue> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 const int oo=0x3f3f3f3f; 6 struct int_2{int TIME;int NO;}; 7 struct pnt{ 8 int hd; 9 int lyr; 10 int now; 11 }p[1000000]; 12 struct ent{ 13 int twd; 14 int vls; 15 int lst; 16 int his; 17 }e[5000000]; 18 struct OVO{ 19 int_2 pro; 20 int i; 21 int j; 22 }; 23 int cnt; 24 int n,m; 25 int s,t; 26 int pnum; 27 char tmp[100]; 28 int no[21][21]; 29 int mp[21][21]; 30 bool vis[21][21]; 31 bool hvv[21][21]; 32 std::queue<int>Q; 33 std::queue<OVO>P; 34 std::vector<int>T[1000]; 35 std::vector<int_2>dr[21][21]; 36 void ade(int f,int t,int v) 37 { 38 cnt++; 39 e[cnt].twd=t; 40 e[cnt].vls=v; 41 e[cnt].his=v; 42 e[cnt].lst=p[f].hd; 43 p[f].hd=cnt; 44 return ; 45 } 46 bool bfs(void) 47 { 48 for(int i=1;i<=n;i++) 49 { 50 for(int j=1;j<=m;j++) 51 { 52 if(mp[i][j]==2) 53 { 54 while(!P.empty()) 55 P.pop(); 56 P.push((OVO){(int_2){0,no[i][j]},i,j}); 57 while(!P.empty()) 58 { 59 OVO x=P.front(); 60 P.pop(); 61 int ii=x.i; 62 int jj=x.j; 63 if(vis[ii][jj]) 64 continue; 65 vis[ii][jj]=true; 66 if(mp[ii][jj]==1) 67 dr[ii][jj].push_back(x.pro); 68 x.pro.TIME++; 69 OVO y; 70 y=x; 71 y.i++; 72 if(y.i<=n) 73 { 74 if(mp[y.i][y.j]==1) 75 { 76 P.push(y); 77 } 78 } 79 y=x; 80 y.i--; 81 if(y.i>0) 82 { 83 if(mp[y.i][y.j]==1) 84 { 85 P.push(y); 86 } 87 } 88 y=x; 89 y.j++; 90 if(y.j<=m) 91 { 92 if(mp[y.i][y.j]==1) 93 { 94 P.push(y); 95 } 96 } 97 y=x; 98 y.j--; 99 if(y.j>0) 100 { 101 if(mp[y.i][y.j]==1) 102 { 103 P.push(y); 104 } 105 } 106 } 107 for(int ii=1;ii<=n;ii++) 108 { 109 for(int jj=1;jj<=m;jj++) 110 { 111 if(vis[ii][jj]) 112 hvv[ii][jj]=true; 113 vis[ii][jj]=false; 114 } 115 } 116 } 117 } 118 } 119 for(int i=1;i<=n;i++) 120 { 121 for(int j=1;j<=m;j++) 122 { 123 if(!hvv[i][j]&&mp[i][j]==1) 124 return true; 125 } 126 } 127 return false; 128 } 129 bool Bfs(void) 130 { 131 while(!Q.empty())Q.pop(); 132 for(int i=1;i<=t;i++) 133 p[i].lyr=0; 134 p[s].lyr=1; 135 Q.push(s); 136 while(!Q.empty()) 137 { 138 int x=Q.front(); 139 Q.pop(); 140 for(int i=p[x].hd;i;i=e[i].lst) 141 { 142 int to=e[i].twd; 143 if(p[to].lyr==0&&e[i].vls>0) 144 { 145 p[to].lyr=p[x].lyr+1; 146 if(to==t) 147 return true; 148 Q.push(to); 149 } 150 } 151 } 152 return false; 153 } 154 int Dfs(int x,int fll) 155 { 156 if(x==t) 157 return fll; 158 for(int& i=p[x].now;i;i=e[i].lst) 159 { 160 int to=e[i].twd; 161 if(p[to].lyr==p[x].lyr+1&&e[i].vls>0) 162 { 163 int ans=Dfs(to,std::min(fll,e[i].vls)); 164 if(ans>0) 165 { 166 e[i].vls-=ans; 167 e[((i-1)^1)+1].vls+=ans; 168 return ans; 169 } 170 } 171 } 172 return 0; 173 } 174 int Dinic(void) 175 { 176 int ans=0; 177 while(Bfs()) 178 { 179 for(int i=1;i<=t;i++) 180 p[i].now=p[i].hd; 181 int dlt; 182 while(dlt=Dfs(s,oo)) 183 ans+=dlt; 184 } 185 return ans; 186 } 187 bool Check(int x) 188 { 189 for(int i=1;i<=t;i++) 190 p[i].hd=0; 191 cnt=0; 192 int lcnt=n*m; 193 for(int i=1;i<=n;i++) 194 for(int j=1;j<=m;j++) 195 if(mp[i][j]==2) 196 { 197 T[no[i][j]].clear(); 198 for(int k=0;k<=x;k++) 199 T[no[i][j]].push_back(++lcnt); 200 } 201 s=lcnt+1; 202 t=s+1; 203 for(int i=1;i<=n;i++) 204 { 205 for(int j=1;j<=m;j++) 206 { 207 if(mp[i][j]==1) 208 { 209 ade(s,no[i][j],1); 210 ade(no[i][j],s,0); 211 for(int k=0;k<dr[i][j].size();k++) 212 { 213 if(dr[i][j][k].TIME<=x) 214 { 215 ade(no[i][j],T[dr[i][j][k].NO][dr[i][j][k].TIME],1); 216 ade(T[dr[i][j][k].NO][dr[i][j][k].TIME],no[i][j],0); 217 } 218 } 219 }else if(mp[i][j]==2) 220 { 221 for(int k=0;k<=x;k++) 222 { 223 ade(T[no[i][j]][k],t,1); 224 ade(t,T[no[i][j]][k],0); 225 if(k!=x) 226 { 227 ade(T[no[i][j]][k],T[no[i][j]][k+1],oo); 228 ade(T[no[i][j]][k+1],T[no[i][j]][k],0); 229 } 230 } 231 } 232 } 233 } 234 return pnum==Dinic(); 235 } 236 int main() 237 { 238 // freopen("a.in","r",stdin); 239 scanf("%d%d",&n,&m); 240 for(int i=1;i<=n;i++) 241 { 242 scanf("%s",tmp+1); 243 for(int j=1;j<=m;j++) 244 { 245 no[i][j]=++cnt; 246 if(tmp[j]=='X') 247 mp[i][j]=0; 248 if(tmp[j]=='.') 249 mp[i][j]=1, 250 pnum++; 251 if(tmp[j]=='D') 252 mp[i][j]=2; 253 } 254 } 255 cnt=0; 256 if(bfs()) 257 { 258 puts("impossible"); 259 return 0; 260 } 261 int l=0,r=1000; 262 int ans; 263 while(l<=r) 264 { 265 int mid=(l+r)>>1; 266 if(Check(mid)) 267 { 268 ans=mid; 269 r=mid-1; 270 }else 271 l=mid+1; 272 } 273 printf("%d ",ans); 274 return 0; 275 }