【BZOJ】1189: [HNOI2007]紧急疏散evacuate(二分+bfs+网络流)
http://www.lydsy.com/JudgeOnline/problem.php?id=1189
表示完全不会QAQ。。。。
于是膜拜题解orz
二分时间。。。。。。。。。。。
于是转换成判定性问题:即如何在有限时间内通过。
假设当前有t时间可供通过。。。那么每一个门最多能通过t个人。。。。。。。。
然后将所有能够到达门的点连边,容量为无限。。。。
然后源向每个可行点连边。。容量1。。
然后每个门向汇连边。。容量为t。。
然后判断即可。。。。
(一开始bfs写错了啊QAQ。。
#include <cstdio>
#include <cstring>
#include <cmath>
#include <string>
#include <iostream>
#include <algorithm>
#include <queue>
#include <set>
#include <map>
using namespace std;
typedef long long ll;
#define rep(i, n) for(int i=0; i<(n); ++i)
#define for1(i,a,n) for(int i=(a);i<=(n);++i)
#define for2(i,a,n) for(int i=(a);i<(n);++i)
#define for3(i,a,n) for(int i=(a);i>=(n);--i)
#define for4(i,a,n) for(int i=(a);i>(n);--i)
#define CC(i,a) memset(i,a,sizeof(i))
#define read(a) a=getint()
#define print(a) printf("%d", a)
#define dbg(x) cout << (#x) << " = " << (x) << endl
#define error(x) (!(x)?puts("error"):0)
#define rdm(x, i) for(int i=ihead[x]; i; i=e[i].next)
inline const int getint() { int r=0, k=1; char c=getchar(); for(; c<'0'||c>'9'; c=getchar()) if(c=='-') k=-1; for(; c>='0'&&c<='9'; c=getchar()) r=r*10+c-'0'; return k*r; } const int N=415, oo=~0u>>1;
const int dx[4]={1, -1, 0, 0}, dy[4]={0, 0, -1, 1};
int ihead[N], cnt=1;
struct dat { int next, to, from, cap; }e[N*N*2];
void add(int u, int v, int c) {
e[++cnt].next=ihead[u]; ihead[u]=cnt; e[cnt].from=u; e[cnt].to=v; e[cnt].cap=c;
e[++cnt].next=ihead[v]; ihead[v]=cnt; e[cnt].from=v; e[cnt].to=u; e[cnt].cap=0;
}
int p[N], d[N], gap[N], cur[N];
int isap(int s, int t, int n) {
for1(i, 0, n) p[i]=0, d[i]=0, gap[i]=0, cur[i]=ihead[i];
gap[0]=n; int ret=0, f, u=s, i;
while(d[s]<n) {
for(i=cur[u]; i; i=e[i].next) if(e[i].cap && d[e[i].to]+1==d[u]) break;
if(i) {
p[e[i].to]=cur[u]=i; u=e[i].to;
if(u==t) {
for(f=oo; u!=s; u=e[p[u]].from) f=min(f, e[p[u]].cap);
for(u=t; u!=s; u=e[p[u]].from) e[p[u]].cap-=f, e[p[u]^1].cap+=f;
ret+=f;
}
}
else {
if(!(--gap[d[u]])) break;
d[u]=n; cur[u]=ihead[u];
for(i=ihead[u]; i; i=e[i].next) if(e[i].cap && d[e[i].to]+1<d[u]) d[u]=d[e[i].to]+1;
++gap[d[u]];
if(u!=s) u=e[p[u]].from;
}
}
return ret;
}
int dis[N][23][23], n, tot, m, a[30][30], S, T;
struct Q { int x, y; }q[N];
inline int ID(int x, int y) { return (x-1)*m+y; }
void bfs(int x, int y, int d[23][23]) {
int front=0, tail=0;
for1(i, 1, n) for1(j, 1, m) d[i][j]=oo;
q[tail].x=x, q[tail].y=y; ++tail;
d[x][y]=0;
Q tp;
while(front!=tail) {
tp=q[front++];
x=tp.x, y=tp.y;
rep(i, 4) {
int fx=dx[i]+x, fy=dy[i]+y;
if(fx<1 || fy<1 || fx>n || fy>m || a[fx][fy]!=1 || d[fx][fy]!=oo) continue;
d[fx][fy]=d[x][y]+1;
q[tail].x=fx; q[tail].y=fy; ++tail;
}
}
//for1(i, 1, n) { for1(j, 1, m) printf("%d ", d[i][j]==oo?0:d[i][j]); puts(""); } puts("");
}
void build() {
for1(i, 1, n) for1(j, 1, m) if(a[i][j]==2)
bfs(i, j, dis[ID(i, j)]);
}
bool check(int t) {
for1(i, 1, T) ihead[i]=0;
cnt=1;
for1(i, 1, n) for1(j, 1, m) if(a[i][j]==2) {
int id=ID(i, j);
for1(x, 1, n) for1(y, 1, m) if(a[x][y]==1 && dis[id][x][y]<=t)
add(ID(x, y), id, oo);
add(id, T, t);
}
for1(i, 1, n) for1(j, 1, m) if(a[i][j]==1) add(S, ID(i, j), 1);
return isap(S, T, T)==tot;
}
int main() {
read(n); read(m); S=n*m+1, T=S+1;
for1(i, 1, n) for1(j, 1, m) { char c=getchar(); while(c!='X'&&c!='.'&&c!='D') c=getchar(); if(c=='.') a[i][j]=1, ++tot; if(c=='D') a[i][j]=2; }
build();
int l=0, r=n*m+1, mid;
while(l<=r) {
mid=(l+r)>>1;
if(check(mid)) r=mid-1;
else l=mid+1;
}
if(!check(r+1)) puts("impossible");
else printf("%d\n", r+1);
return 0;
}
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
XXXXX
X...D
XX.XX
X..XX
XXDXX
Sample Output
HINT
Source
【BZOJ】1189: [HNOI2007]紧急疏散evacuate(二分+bfs+网络流)的更多相关文章
- bzoj 1189 [HNOI2007]紧急疏散evacuate 二分+网络流
[HNOI2007]紧急疏散evacuate Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 3626 Solved: 1059[Submit][St ...
- BZOJ 1189: [HNOI2007]紧急疏散evacuate( BFS + 二分答案 + 匈牙利 )
我们可以BFS出每个出口到每个人的最短距离, 然后二分答案, 假设当前答案为m, 把一个出口拆成m个表示m个时间, 点u到出口v的距离为d, 那么u->v的[d, m]所有点连边, 然后跑匈牙利 ...
- bzoj 1189: [HNOI2007]紧急疏散evacuate 分层图最大流_拆点_二分
Description 发生了火警,所有人员需要紧急疏散!假设每个房间是一个N M的矩形区域.每个格子如果是'.',那么表示这是一 块空地:如果是'X',那么表示这是一面墙,如果是'D',那么表示这是 ...
- BZOJ 1189 [HNOI2007]紧急疏散evacuate
Description 发生了火警,所有人员需要紧急疏散!假设每个房间是一个N M的矩形区域.每个格子如果是'.',那么表示这是一块空地:如果是'X',那么表示这是一面墙,如果是'D',那么表示这是一 ...
- BZOJ1189: [HNOI2007]紧急疏散evacuate 二分+最大流
1189: [HNOI2007]紧急疏散evacuate Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1132 Solved: 412[Submi ...
- 1189: [HNOI2007]紧急疏散evacuate - BZOJ
Description 发生了火警,所有人员需要紧急疏散!假设每个房间是一个N M的矩形区域.每个格子如果是'.',那么表示这是一块空地:如果是'X',那么表示这是一面墙,如果是'D',那么表示这是一 ...
- 1189: [HNOI2007]紧急疏散evacuate
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 3831 Solved: 1119[Submit][Status][Discuss] Descript ...
- BZOJ1189: [HNOI2007]紧急疏散evacuate(二分答案,最大流)
Description 发生了火警,所有人员需要紧急疏散!假设每个房间是一个N M的矩形区域.每个格子如果是'.',那么表示这是一 块空地:如果是'X',那么表示这是一面墙,如果是'D',那么表示这是 ...
- bzoj千题计划132:bzoj1189: [HNOI2007]紧急疏散evacuate
http://www.lydsy.com/JudgeOnline/problem.php?id=1189 二分答案 源点向人连边,流量为1 门拆为mid个点,同一个门的第j个点向第j+1个点连边,流量 ...
随机推荐
- 自动化运维之puppet的学习(如何找到你需要的模块)
https://forge.puppetlabs.com/ puppet 模块下载 http://kisspuppet.com/2014/01/14/puppet_forge_modules/ pu ...
- Javascript样例之文档章节滚动全版(DOM)
aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAABBMAAAC5CAIAAAD1bOCRAAAMEUlEQVR4nO3d4XEbyREGUGRCZQDGcG
- python的类变量与实例变量
python的类内部定义的变量 ,形式上没有区分实例变量和类变量(java的静态变量),测试结果如下:
- apache ab压力测试报错(apr_socket_recv: Connection reset by peer (104))
apache ab压力测试报错(apr_socket_recv: Connection reset by peer (104)) 今天用apache 自带的ab工具测试,当并发量达到1000多的时 ...
- linux中pip安装步骤与使用详解
pip类似RedHat里面的yum,安装软件非常方便.本节详细介绍pip的安装.以及使用方法,希望文章对各位了解pip的安装与使用带来帮助. 1.pip下载安装1.1 pip下载 代码如下 复制代码 ...
- springMVC的一些工具类
springMVC的一些工具类,主要有转换器,读取器 读取文件: package cn.edu.hbcf.common.springmvc; import java.util.HashMap; imp ...
- [Git] Git 文件归档, include submodule
git archive命令,可以对任意提交对应的目录树建立归档. $ git archive -o latest.zip HEAD 基于最新提交建立归档文件latest.zip $ git ar ...
- July 18th, Week 30th Monday, 2016
Truth needs no color; beauty, no pencil. 真理不需要色彩,美丽无需涂饰. Most of the time, giving some color to trut ...
- 6个朋友(codevs 2832)
2832 6个朋友 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题解 题目描述 Description 有这么一种说法:认识6个人,你就认识全世 ...
- popular net
陈皓<跟我一起写makefile>http://blog.csdn.net/haoel/article/details/2886/