[HNOI2007]紧急疏散EVACUATE

题目描述

发生了火警,所有人员需要紧急疏散!假设每个房间是一个N M的矩形区域。每个格子如果是'.',那么表示这是一块空地;如果是'X',那么表示这是一面墙,如果是'D',那么表示这是一扇门,人们可以从这儿撤出房间。已知门一定在房间的边界上,并且边界上不会有空地。最初,每块空地上都有一个人,在疏散的时候,每一秒钟每个人都可以向上下左右四个方向移动一格,当然他也可以站着不动。疏散开始后,每块空地上就没有人数限制了(也就是说每块空地可以同时站无数个人)。但是,由于门很窄,每一秒钟只能有一个人移动到门的位置,一旦移动到门的位置,就表示他已经安全撤离了。现在的问题是:如果希望所有的人安全撤离,最短需要多少时间?或者告知根本不可能。

输入输出格式

输入格式:

输入文件第一行是由空格隔开的一对正整数N与M,3<=N <=20,3<=M<=20,以下N行M列描述一个N M的矩阵。其中的元素可为字符'.'、'X'和'D',且字符间无空格。

输出格式:

只有一个整数K,表示让所有人安全撤离的最短时间,如果不可能撤离,那么输出'impossible'(不包括引号)。

输入输出样例

输入样例#1:

5 5
XXXXX
X...D
XX.XX
X..XX
XXDXX
输出样例#1:

3

试题分析:创建超级源S,超级汇T
     方便起见,先对于每一块空地BFS求出它到每个能到达的门的距离
     然后二分答案,建图。
     S连到每一个节点,容量为1的边。代表每个位置上有一个人。
     简单粗暴的建图方法就是直接对于每个点将其每个时刻的点都建出来,会T一个点。
     考虑优化,发现我们不用管每个时刻这个门的状态是什么,而是只用关心最后从这个门出去多少个。
     所以我们的建图方法如下:
     ①S连接到每一块空地容量为1
     ②每一块空地连接到其在二分答案时间内可以到的门,容量为1
     ③将每一个门连向T,容量为X(二分的时间)
     
代码:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<queue>
#include<algorithm>
using namespace std;
inline int read(){
int x=0,f=1;char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
for(;isdigit(c);c=getchar()) x=x*10+c-'0';
return x*f;
}
#define LL long long
const int MAXN = 500001;
const int MAXN2 = 1000001;
const int INF = 9999999; int N,M;
int Root[MAXN2+1],Next[MAXN2+1],Node[MAXN+1],C[MAXN2+1];
int cnt;
char Map[21][21]; void insert(int u,int v,int w){
C[cnt]=w; Node[cnt]=v;
Next[cnt]=Root[u]; Root[u]=cnt++;
return ;
}
struct data{
int x,y,tm;
};
bool vis[21][21];
int dis[21][21][21][21];
int dist[5][2]={{0,-1},{0,1},{1,0},{-1,0}};
int ans; int S,T,KT;
void BFST(){
data t;
for(int i=1;i<=N;i++){
for(int j=1;j<=M;j++){
if(Map[i][j]=='.'){
++KT;
queue<data> Que;
t.x=i; t.y=j; t.tm=0;
Que.push(t);
memset(vis,0,sizeof(vis)); vis[i][j]=true;
while(!Que.empty()){
data k=Que.front(); Que.pop();
if(Map[k.x][k.y]=='D'){
dis[i][j][k.x][k.y]=k.tm;
continue;
}
for(int l=0;l<4;l++){
int xx=k.x+dist[l][0];
int yy=k.y+dist[l][1];
if(xx<1||yy<1||xx>N||yy>M||Map[xx][yy]=='X'||vis[xx][yy]) continue;
t.x=xx; t.y=yy; t.tm=k.tm+1;
vis[xx][yy]=true;
Que.push(t);
}
}
}
}
}
return ;
}
int D[MAXN+1];
bool BFS(){
queue<int> Que; Que.push(S);
memset(D,0,sizeof(D)); D[S]=1;
while(!Que.empty()){
int k=Que.front(); Que.pop();
for(int x=Root[k];x>-1;x=Next[x]){
int v=Node[x];
if(C[x]>0&&!D[v]){
D[v]=D[k]+1;
if(v==T) return true;
Que.push(v);
}
}
}
return false;
}
int cur[MAXN+1];
int DFS(int k,int t){
if(k==T) return t;
int res=0;
for(int x=cur[k];x>-1;x=Next[x]){
int v=Node[x];
if(C[x]>0&&D[v]==D[k]+1){
int tmp=DFS(v,min(C[x],t));
if(!tmp) continue;
C[x]-=tmp; t-=tmp; C[x^1]+=tmp; res+=tmp;
if(!t) return res;
}
cur[k]=x;
}
if(!res) D[k]=-1;
return res;
}
bool check(int K){
cnt=0;
for(int i=0;i<=MAXN;i++) Root[i]=-1;
memset(Next,0,sizeof(Next)); S=0,T=500000;
memset(C,0,sizeof(C)); memset(Node,0,sizeof(Node));
for(int i=1;i<=N;i++){
for(int j=1;j<=M;j++){
if(Map[i][j]=='.'){
insert(S,(i-1)*M+j,1);
insert((i-1)*M+j,S,0);
for(int l1=1;l1<=N;l1++){
for(int l2=1;l2<=M;l2++){
if(Map[l1][l2]=='D'&&dis[i][j][l1][l2]&&dis[i][j][l1][l2]<=K){
insert((i-1)*M+j,(l1-1)*M+l2,1);
insert((l1-1)*M+l2,(i-1)*M+j,0);
}
}
}
}
else if(Map[i][j]=='D'){
insert((i-1)*M+j,T,K);
insert(T,(i-1)*M+j,0);
}
}
}
int ans=0; --cnt;
while(BFS()){
for(int i=0;i<=N*M;i++) cur[i]=Root[i];
ans+=DFS(S,INF);
}
return ans>=KT;
} int main(){
N=read(),M=read();
for(int i=1;i<=N;i++){
for(int j=1;j<=M;j++)
cin>>Map[i][j];
}
BFST();
int l=0,r=400;
while(l<=r){
int mid=(l+r)>>1;
if(check(mid)) ans=mid,r=mid-1;
else l=mid+1;
}
if(ans) printf("%d\n",ans);
else puts("impossible");
}

  

 

【二分答案】【最大流】[HNOI2007]紧急疏散EVACUATE的更多相关文章

  1. BZOJ1189: [HNOI2007]紧急疏散evacuate 二分+最大流

    1189: [HNOI2007]紧急疏散evacuate Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1132  Solved: 412[Submi ...

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

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

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

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

  4. P3191 [HNOI2007]紧急疏散EVACUATE(费用流)

    P3191 [HNOI2007]紧急疏散EVACUATE 费用流+卡常优化 我们只关心一个人通过门时的时间,在空地的行走时间可以分层维护 于是根据时间分层,到门的时候再计算代价,即代价$=$层数 每经 ...

  5. Bzoj1189 [HNOI2007]紧急疏散evacuate

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

  6. [HNOI2007]紧急疏散EVACUATE (湖南2007年省选)

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

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

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

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

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

  9. 【BZOJ1189】[HNOI2007]紧急疏散evacuate 动态加边网络流

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

随机推荐

  1. Quick-Cocos2dx-Community_3.6.3_Release 编译时libtiff.lib 无法解析

    Quick-Cocos2dx-Community_3.6.3_Release 使用VS2012编译,报错: libtiff.lib lnk2001 无法解析的外部符号 ltod3 类似于上面这种,刚才 ...

  2. bzoj 2440 dfs序

    首先我们可以做一遍dfs,用一个队列记录每个点进出的顺序,当每个点访问的时候que[tot++]=x,记为in[x],当结束dfs的时候que[tot++]=x,记为out[x],这样处理出来的队列, ...

  3. 玩一下易语言 "和"字有多种读音,注定了它的重要性!!

    变量名 类型 静态 数组 备注 拼音 文本型   0   测试的汉字 文本型       有几种发音 整数型       i 整数型       测试用的汉字 = “和” 有几种发音 = 取发音数目 ...

  4. solaris如何启动ssh服务

    先查看一下ssh服务状态:# svcs或# svcs | grep sshonline Aug_07 svc:/network/ssh:default 如需要关闭ssh服务(关闭完可以 svcs | ...

  5. 第一章:读取文件一行IO::File

    #!c:\\perl\\bin\\perl.exe use IO::File; #读取一行 my $fd = IO::File->new('perl.txt'); my $one_line = ...

  6. php中的parse_ini_file函数

    作用:parse_ini_file() 函数解析一个配置文件,并以数组的形式返回其中的设置 格式:parse_ini_file(file,true)// (第二个参数为可选参数.如果设置为 true, ...

  7. Python模块学习 - ConfigParser

    配置文件 很多软件都用到了配置文件,像git运行的时候会读取~/gitconfig,MySQL运行的时候会读取/etc/my.cnf,Python 提供的包管理工具pip命令,也会去读取~/.pip/ ...

  8. WoW[www]

    WoWBeez https://github.com/StealtheeEU/WoWBeez https://github.com/mtucker6784/Elysium https://github ...

  9. nodejs 优雅的连接 mysql

    1.mysql 及 promise-mysql nodejs 连接 mysql 有成熟的npm包 mysql ,如果需要promise,建议使用 promise-mysql: npm:https:// ...

  10. python windows下安装celery调度任务时出错

    由于celery 4.0不支持windows系统.所以用命令pip install Celery安装的celery是最新版4.0的不能在windows下运行. 在windows命令窗口运行: cele ...