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

 

你可能感兴趣的:(2007)