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这个距离标号,我想继续利用上次的标号,后来发现不行因为断层以后,有的点距离标号变成最大的,就不能再经过它了,当时调了好久的说

 const
fx:array[..]of longint=(,,-,);
fy:array[..]of longint=(,,,-);
var
map:array[..,..]of char;
node:array[..,..]of longint;
f:array[..,..,..]of longint;
door:array[..,..]of longint;
n,m,menn,doorn,tot:longint; procedure init;
var
i,j:longint;
begin
readln(n,m);
for i:= to n do
begin
for j:= to m do
begin
read(map[i,j]);
if map[i,j]='.' then
begin
inc(menn);
inc(tot);
node[i,j]:=tot;
end;
if map[i,j]='D' then
begin
inc(doorn);
door[doorn,]:=i;
door[doorn,]:=j;
inc(tot);
node[i,j]:=tot;
end;
end;
readln;
end;
end; var
flag,vis:array[..,..]of boolean;
x,y:array[..]of longint; procedure bfs;
var
i,j,head,tail:longint;
begin
fillchar(f,sizeof(f),<<);
fillchar(vis,sizeof(vis),true);
for i:= to doorn do
begin
fillchar(flag,sizeof(flag),true);
f[door[i,],door[i,],i]:=;
head:=;
tail:=;
x[]:=door[i,];
y[]:=door[i,];
flag[x[],y[]]:=false;
while head<=tail do
begin
for j:= to do
if (x[head]+fx[j]>)and(x[head]+fx[j]<=n)and(y[head]+fy[j]>)and(y[head]+fy[j]<=m) then
if map[x[head]+fx[j],y[head]+fy[j]]='.' then
if flag[x[head]+fx[j],y[head]+fy[j]] then
begin
inc(tail);
x[tail]:=x[head]+fx[j];
y[tail]:=y[head]+fy[j];
vis[x[tail],y[tail]]:=false;
f[x[tail],y[tail],i]:=f[x[head],y[head],i]+;
flag[x[tail],y[tail]]:=false;
end;
inc(head);
end;
end;
for i:= to n do
for j:= to m do
if (map[i,j]='.')and(vis[i,j]) then
begin
write('impossible');
halt;
end;
end; var
a:array[..,..]of longint;
dis,vh,pre,his:array[..]of longint;
flow,time,aug,num,min,hui:longint;
find:boolean; procedure sap;
var
i,j,k:longint;
begin
aug:=maxlongint;
fillchar(vh,sizeof(vh),);
vh[]:=num+;
fillchar(dis,sizeof(dis),);
i:=;
while dis[]<=num do
begin
his[i]:=aug;
find:=false;
for j:= to num+ do
if (a[i,j]>)and(dis[i]=dis[j]+) then
begin
find:=true;
if aug>a[i,j] then aug:=a[i,j];
pre[j]:=i;
i:=j;
if i=hui then
begin
inc(flow,aug);
while i<> do
begin
k:=pre[i];
inc(a[i,k]);
dec(a[k,i]);
i:=k;
end;
aug:=maxlongint;
end;
break;
end;
if find then continue;
min:=num;
for j:= to num+ do
if (a[i,j]>)and(min>dis[j]) then min:=dis[j];
dec(vh[dis[i]]);
inc(vh[min+]);
if vh[dis[i]]= then break;
dis[i]:=min+;
if i<> then
begin
i:=pre[i];
aug:=his[i];
end;
end;
end; procedure work;
var
i,j,k:longint;
begin
num:=menn+doorn+;
hui:=num+;
for i:= to n do
for j:= to m do
if map[i,j]='.' then inc(a[,node[i,j]]);
while flow<menn do
begin
inc(time);
for i:= to n do
for j:= to m do
if map[i,j]='.' then
for k:= to doorn do
if f[i,j,k]=time then inc(a[node[i,j],node[door[k,],door[k,]]]);
for i:= to doorn do
inc(a[node[door[i,],door[i,]],hui]);
sap;
end;
write(time);
end; begin
init;
bfs;
work;
end.

1189: [HNOI2007]紧急疏散evacuate - BZOJ的更多相关文章

  1. BZOJ 1189: [HNOI2007]紧急疏散evacuate( BFS + 二分答案 + 匈牙利 )

    我们可以BFS出每个出口到每个人的最短距离, 然后二分答案, 假设当前答案为m, 把一个出口拆成m个表示m个时间, 点u到出口v的距离为d, 那么u->v的[d, m]所有点连边, 然后跑匈牙利 ...

  2. bzoj 1189 [HNOI2007]紧急疏散evacuate 二分+网络流

    [HNOI2007]紧急疏散evacuate Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 3626  Solved: 1059[Submit][St ...

  3. AC日记——[HNOI2007]紧急疏散evacuate bzoj 1189

    [HNOI2007]紧急疏散evacuate 思路: 处理每个人到门的最短路: 然后二分答案: s向人连边流量1: 人向门拆分后的点连边流量1(拆成400,前一个点连当前点流量INF): 然后门向t连 ...

  4. 【BZOJ】1189: [HNOI2007]紧急疏散evacuate(二分+bfs+网络流)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1189 表示完全不会QAQ.... 于是膜拜题解orz 二分时间........... 于是转换成判定 ...

  5. BZOJ 1189 [HNOI2007]紧急疏散evacuate

    Description 发生了火警,所有人员需要紧急疏散!假设每个房间是一个N M的矩形区域.每个格子如果是'.',那么表示这是一块空地:如果是'X',那么表示这是一面墙,如果是'D',那么表示这是一 ...

  6. bzoj 1189: [HNOI2007]紧急疏散evacuate 分层图最大流_拆点_二分

    Description 发生了火警,所有人员需要紧急疏散!假设每个房间是一个N M的矩形区域.每个格子如果是'.',那么表示这是一 块空地:如果是'X',那么表示这是一面墙,如果是'D',那么表示这是 ...

  7. 1189: [HNOI2007]紧急疏散evacuate

    Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 3831  Solved: 1119[Submit][Status][Discuss] Descript ...

  8. bzoj千题计划132:bzoj1189: [HNOI2007]紧急疏散evacuate

    http://www.lydsy.com/JudgeOnline/problem.php?id=1189 二分答案 源点向人连边,流量为1 门拆为mid个点,同一个门的第j个点向第j+1个点连边,流量 ...

  9. Bzoj1189 [HNOI2007]紧急疏散evacuate

    1189: [HNOI2007]紧急疏散evacuate Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2293  Solved: 715 Descr ...

随机推荐

  1. asp.net mvc 的几种分页Pager

    第一种 /// <summary> /// 分页Pager显示 /// </summary> /// <param name="html">&l ...

  2. django 学习-7 模型数据操作

    1.首先还是创建办一个项目和一个应用 django.admin.py   startproject    ssj cd  ssj django.admin.py   startapp    sdj 那 ...

  3. HDOJ2018母牛的故事

    母牛的故事 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submi ...

  4. 网易新闻RSS阅读器

    首先需要分析网易RSS订阅中心的网页布局情况. 网易RSS订阅中心:http://www.163.com/rss/ 你会发现RSS文件由一个<channel>元素及其子元素组成,除了频道本 ...

  5. android NDK 开发步骤

    NDK开发一般分为一下几个步骤:(默认你已经安装好了NDK和android开发环境) 1.创建一个项目 2.创建JNI目录 3.编写nativejava层方法 4.生成JNI头文件 (1)编写java ...

  6. PullToRefreshListView手动刷新问题

    1.第一次进入界面刷新无效,需要延时刷新 new Handler().postDelayed(new Runnable() { @Override public void run() { // TOD ...

  7. php 中cookie和session的用法比较

    1.cookie数据存放在客户的浏览器上,session数据放在服务器上. 2.cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗,考虑到安全应当使用session. ...

  8. (转)Hprose与WCF在云计算平台Azure上的对决

    Windows Azure Platform是一个运行在微软数据中心的云计算平台.它包括一个云计算操作系统和一个为开发者提供的服务集合.开发人员创建的应用既可以直接在该平台 中运行,也可以使用该云计算 ...

  9. docker & nodejs

    Docker 部署 Node js demo程序 1.准备node js程序,使用express框架. mkdir demo 在demo文件夹下建立package.json { "name& ...

  10. springMVC+Hibernate常用的配置文件

    每次写一个新的web项目时都要写配置文件.比较麻烦,现在把常用到的配置文件记录下来,方便以后使用 web.xml <?xml version="1.0" encoding=& ...