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这个距离标号,我想继续利用上次的标号,后来发现不行因为断层以后,有的点距离标号变成最大的,就不能再经过它了,当时调了好久的说
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的更多相关文章
- BZOJ 1189: [HNOI2007]紧急疏散evacuate( BFS + 二分答案 + 匈牙利 )
我们可以BFS出每个出口到每个人的最短距离, 然后二分答案, 假设当前答案为m, 把一个出口拆成m个表示m个时间, 点u到出口v的距离为d, 那么u->v的[d, m]所有点连边, 然后跑匈牙利 ...
- bzoj 1189 [HNOI2007]紧急疏散evacuate 二分+网络流
[HNOI2007]紧急疏散evacuate Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 3626 Solved: 1059[Submit][St ...
- AC日记——[HNOI2007]紧急疏散evacuate bzoj 1189
[HNOI2007]紧急疏散evacuate 思路: 处理每个人到门的最短路: 然后二分答案: s向人连边流量1: 人向门拆分后的点连边流量1(拆成400,前一个点连当前点流量INF): 然后门向t连 ...
- 【BZOJ】1189: [HNOI2007]紧急疏散evacuate(二分+bfs+网络流)
http://www.lydsy.com/JudgeOnline/problem.php?id=1189 表示完全不会QAQ.... 于是膜拜题解orz 二分时间........... 于是转换成判定 ...
- BZOJ 1189 [HNOI2007]紧急疏散evacuate
Description 发生了火警,所有人员需要紧急疏散!假设每个房间是一个N M的矩形区域.每个格子如果是'.',那么表示这是一块空地:如果是'X',那么表示这是一面墙,如果是'D',那么表示这是一 ...
- bzoj 1189: [HNOI2007]紧急疏散evacuate 分层图最大流_拆点_二分
Description 发生了火警,所有人员需要紧急疏散!假设每个房间是一个N M的矩形区域.每个格子如果是'.',那么表示这是一 块空地:如果是'X',那么表示这是一面墙,如果是'D',那么表示这是 ...
- 1189: [HNOI2007]紧急疏散evacuate
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 3831 Solved: 1119[Submit][Status][Discuss] Descript ...
- bzoj千题计划132:bzoj1189: [HNOI2007]紧急疏散evacuate
http://www.lydsy.com/JudgeOnline/problem.php?id=1189 二分答案 源点向人连边,流量为1 门拆为mid个点,同一个门的第j个点向第j+1个点连边,流量 ...
- Bzoj1189 [HNOI2007]紧急疏散evacuate
1189: [HNOI2007]紧急疏散evacuate Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 2293 Solved: 715 Descr ...
随机推荐
- js中关于事件处理函数名后面是否带括号的问题
今天总结一个关于事件处理程序的小细节.首先回顾一下事件处理的一些概念. JS中的事件处理(事件绑定)就是让某种或某些事件触发某些活动.有两种常见的形式,分别是DOM Level 0 和DOM Leve ...
- MySQL数据库的存储结构
--把若干条sql语句封装起来,起个名字,叫做过程,也是没有返回值的函数 --把这个过程存储在数据库中->存储过程 --存储过程的创建过程 create procedure proceduceN ...
- ActiveMQ(5.10.0) - Message Redelivery and DLQ Handling
When messages expire on the ActiveMQ broker (they exceed their time-to-live, if set) or can’t be red ...
- Android通过LIstView显示文件列表
[绥江一百]http://www.sj100.net 欢迎,进入绥江一百感谢点击[我的小网站,请大家多 ...
- 关于JAVA System常见类的一些总结
一.JAVA System类概述 1.概述: System 类是一个抽象类,所有的字段和方法都是静态的,即不能被实例化.其中包含一些有用的类字段和方法,它不能被实例化.在 System 类提供的设施中 ...
- 免费主机kilu使用
我也是看了这篇文章:http://www.cnblogs.com/tenny/archive/2011/03/30/1999957.html 采取申请注册. 主机申请地址:http://www.kil ...
- javascript 笔记——bind 用法小技巧
$(function(){ //代码阅读能力 function speak(name){ return "Hello " + name; } //此处写代码 //方法一 //重点是 ...
- [zz]安装PostgreSQL数据库(Linux篇)
0.编译环境 Linux: CentOS 5.5 gcc: 4.1.2 1. 安装PostgreSQL 1) 解压postgresql-9.1.7.tar.bz2 #tar jxvf postgres ...
- 在Apache中开启虚拟主机
最近在自学LAMP,在Apache中尝试着开启虚拟主机的时候,遇到了挺多麻烦的,这里也顺便总结一下,在Apache中开启虚拟主机的时候,主要有下面几个步骤: 1.新建一个文件夹作为虚拟主机,用来存储网 ...
- jQuery Mobile里xxx怎么用呀?(集成篇)
jQuery Mobile如何使用GA(Google Analytics)? 什么是GA: http://baike.baidu.com/view/34729.htm http://www.googl ...