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 ...
随机推荐
- 小议jQuery中的事件
学了jQuery这么长时间,到这里真的有一种柳暗花明又一村的感觉,在这里先表达一下自己学这一章节的happy心情吧(在严厉的金工实习老师眼皮底下偷偷学习,当然还有各种nerves~). 1加载DOM ...
- 会话—cookie
什么是会话? 会话可简单理解为:用户开一个浏览器,点击多个超链接,访问服务器多个web资源,然后关闭浏览器,整个过程称之为一个会话. 会话过程中要解决的一些问题? 每个用户在使 ...
- 搭建私有git代码托管服务就是这么简单(简单5步)
部署一个git代码托管服务就是这么简单 --基于阿里云ecs以docker容器运行gogs代码托管服务 部署步骤: 1.新建ecs云主机,选定操作系统为ubuntu 12.4tls 2.搭建docke ...
- android输入框显示在软键盘上边
有时候在界面需要输入的时候,如果输入框在界面的下方,软键盘弹出的时候会遮挡输入框界面,对用户的体验不是很好. 在网上找的别人的解决方案 首先: 清单文件里面配置:android:windowSoftI ...
- AjaxPro使用方法
无意中看到同事用AjaxPro用,看到很不错,特长是前后台传输数据特别方便. 最好的教材就是拿到就可以用,方便大家. 以前数据传输用FORM提交,或者在前台用JASON拼接然后通过AJAX方式提交.总 ...
- c#基础笔记-----------集合
首先所谓集合是用于管理对象的容器类.一方面集合将独立的对象汇集成群集,作为一个群集来管理,以便进行整体性操作:而另一方面,集合可以方便地获取群集中的个体,进行个体化操作.在.Net中,集合被封装为对象 ...
- Qt学习总结-ui篇(二)
qccs定义圆角 border-radius:10px; 如果想给特定位置定义圆角,如: 左上角:border-left-top-radius:10px; 右下角色:border-right-bo ...
- 一个疑惑的的问题-ntvdm.exe进程
今天测试反馈了一个问题,在启动我们程序某个模块的程序时,会立即出现一个ntvdm.exe进程,此进程会占用大量的系统资源,导致系统卡住. 当第一眼看到这个现象时,以为是电脑中毒了,所以立即在网上查. ...
- python练习 根据日志中的ip和url排序
#!/usr/bin/env python #coding:utf-8 def open_file(file_name): res={} with open(file_name) as f: for ...
- 单纯形法C++实现
作者:jostree 转载请注明出处 http://www.cnblogs.com/jostree/p/4156685.html 使用单纯型法来求解线性规划,输入单纯型法的松弛形式,是一个大矩阵,第一 ...