1189: [HNOI2007]紧急疏散evacuate - BZOJ

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

 

先bfs出最短路,再枚举时间t,用网络流来判断是否可以安全撤离(至于怎么证明它的正确性,我不知道,网上到处都是这样写的)

本来一直纠结在dis这个距离标号,我想继续利用上次的标号,后来发现不行因为断层以后,有的点距离标号变成最大的,就不能再经过它了,当时调了好久的说

 

  1 const
  2     fx:array[1..4]of longint=(1,0,-1,0);
  3     fy:array[1..4]of longint=(0,1,0,-1);
  4 var
  5     map:array[0..20,0..20]of char;
  6     node:array[0..20,0..20]of longint;
  7     f:array[0..20,0..20,0..400]of longint;
  8     door:array[0..400,0..1]of longint;
  9     n,m,menn,doorn,tot:longint;
 10  
 11 procedure init;
 12 var
 13     i,j:longint;
 14 begin
 15     readln(n,m);
 16     for i:=1 to n do
 17       begin
 18         for j:=1 to m do
 19           begin
 20             read(map[i,j]);
 21             if map[i,j]='.' then
 22             begin
 23               inc(menn);
 24               inc(tot);
 25               node[i,j]:=tot;
 26             end;
 27             if map[i,j]='D' then
 28             begin
 29               inc(doorn);
 30               door[doorn,0]:=i;
 31               door[doorn,1]:=j;
 32               inc(tot);
 33               node[i,j]:=tot;
 34             end;
 35           end;
 36         readln;
 37       end;
 38 end;
 39  
 40 var
 41     flag,vis:array[0..20,0..20]of boolean;
 42     x,y:array[0..410]of longint;
 43  
 44 procedure bfs;
 45 var
 46     i,j,head,tail:longint;
 47 begin
 48     fillchar(f,sizeof(f),1<<7);
 49     fillchar(vis,sizeof(vis),true);
 50     for i:=1 to doorn do
 51       begin
 52         fillchar(flag,sizeof(flag),true);
 53         f[door[i,0],door[i,1],i]:=0;
 54         head:=1;
 55         tail:=1;
 56         x[1]:=door[i,0];
 57         y[1]:=door[i,1];
 58         flag[x[1],y[1]]:=false;
 59         while head<=tail do
 60           begin
 61             for j:=1 to 4 do
 62               if (x[head]+fx[j]>0)and(x[head]+fx[j]<=n)and(y[head]+fy[j]>0)and(y[head]+fy[j]<=m) then
 63               if map[x[head]+fx[j],y[head]+fy[j]]='.' then
 64               if flag[x[head]+fx[j],y[head]+fy[j]] then
 65               begin
 66                 inc(tail);
 67                 x[tail]:=x[head]+fx[j];
 68                 y[tail]:=y[head]+fy[j];
 69                 vis[x[tail],y[tail]]:=false;
 70                 f[x[tail],y[tail],i]:=f[x[head],y[head],i]+1;
 71                 flag[x[tail],y[tail]]:=false;
 72               end;
 73             inc(head);
 74           end;
 75       end;
 76     for i:=1 to n do
 77       for j:=1 to m do
 78         if (map[i,j]='.')and(vis[i,j]) then
 79         begin
 80           write('impossible');
 81           halt;
 82         end;
 83 end;
 84  
 85 var
 86     a:array[0..410,0..410]of longint;
 87     dis,vh,pre,his:array[0..410]of longint;
 88     flow,time,aug,num,min,hui:longint;
 89     find:boolean;
 90  
 91 procedure sap;
 92 var
 93     i,j,k:longint;
 94 begin
 95     aug:=maxlongint;
 96     fillchar(vh,sizeof(vh),0);
 97     vh[0]:=num+1;
 98     fillchar(dis,sizeof(dis),0);
 99     i:=0;
100     while dis[0]<=num do
101       begin
102         his[i]:=aug;
103         find:=false;
104         for j:=0 to num+1 do
105           if (a[i,j]>0)and(dis[i]=dis[j]+1) then
106           begin
107             find:=true;
108             if aug>a[i,j] then aug:=a[i,j];
109             pre[j]:=i;
110             i:=j;
111             if i=hui then
112             begin
113               inc(flow,aug);
114               while i<>0 do
115                 begin
116                   k:=pre[i];
117                   inc(a[i,k]);
118                   dec(a[k,i]);
119                   i:=k;
120                 end;
121               aug:=maxlongint;
122             end;
123             break;
124           end;
125         if find then continue;
126         min:=num;
127         for j:=0 to num+1 do
128           if (a[i,j]>0)and(min>dis[j]) then min:=dis[j];
129         dec(vh[dis[i]]);
130         inc(vh[min+1]);
131         if vh[dis[i]]=0 then break;
132         dis[i]:=min+1;
133         if i<>0 then
134         begin
135           i:=pre[i];
136           aug:=his[i];
137         end;
138       end;
139 end;
140  
141 procedure work;
142 var
143     i,j,k:longint;
144 begin
145     num:=menn+doorn+1;
146     hui:=num+1;
147     for i:=1 to n do
148       for j:=1 to m do
149         if map[i,j]='.' then inc(a[0,node[i,j]]);
150     while flow<menn do
151       begin
152         inc(time);
153         for i:=1 to n do
154           for j:=1 to m do
155             if map[i,j]='.' then
156             for k:=1 to doorn do
157               if f[i,j,k]=time then inc(a[node[i,j],node[door[k,0],door[k,1]]]);
158         for i:=1 to doorn do
159           inc(a[node[door[i,0],door[i,1]],hui]);
160         sap;
161       end;
162     write(time);
163 end;
164  
165 begin
166     init;
167     bfs;
168     work;
169 end.
View Code

 

posted @ 2014-03-07 17:01  Randolph87  阅读(363)  评论(0编辑  收藏  举报