[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. 使用.net core abp framework

    abp是一个有用的框架,包含许多功能,可以用来作为脚手架. 直接在官方网站上输入相应的工程名称,选择对应的版本就会下载对应的版本..net core 版本的可以使用后端框架部分来做api,包含了常用框 ...

  2. 对vue中 默认的 config/index.js:配置的详细理解 -【以及webpack配置的理解】-config配置的目的都是为了服务webpack的配置,给不同的编译条件提供配置

    当我们需要和后台分离部署的时候,必须配置config/index.js: 用vue-cli 自动构建的目录里面  (环境变量及其基本变量的配置) var path = require('path') ...

  3. Linux中的vim实用命令 -- (转)

    VI 有2个模式.我自己定义的   1. 命令模式,一开始进去的模式.一些指定的键盘输入会产生不同的效果 2. 输入模式,在命令模式下输入冒号(:) 就可以进入输入模式.按Esc键即可退出命令模式. ...

  4. 常见网络命令之traceroute命令一起其他常用命令

    备注:任何命令+/?就可以显示命令帮助,比如:ipconfig /?. traceroute命令 traceroute是UNIX系统中的名字,用来跟踪一个分组从源点到终点的路径.在Windows系统中 ...

  5. 【转】jpeg文件格式详解

    JPEG(Joint Photographic Experts Group)是联合图像专家小组的英文缩写.它由国际电话与电报咨询委员会CCITT(The International Telegraph ...

  6. Python模块学习 - click

    Click模块 click模块是Flask的作者开发的一个第三方模块,用于快速创建命令行.它的作用与Python标准库的argparse相同,但是,使用起来更简单. click是一个第三方库,因此使用 ...

  7. Python3 xml模块的增删改查

    xml数据示例 ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 <data>     < ...

  8. [Leetcode Week15]Populating Next Right Pointers in Each Node

    Populating Next Right Pointers in Each Node 题解 原创文章,拒绝转载 题目来源:https://leetcode.com/problems/populati ...

  9. VPS速度测试(4):上传下载速度、服务器带宽、Ping响应时间

    1.VPS的速度好坏经常是我们选择某一个VPS商家的重要参考指标,对于国外的VPS主机我们可以执行以下命令来测试VPS入口带宽是多少. wget https://cachefly.cachefly.n ...

  10. 使用 Visual Studio 部署 .NET Core 应用 ——.Net Core 部署到SUSE Linux Enterprise Server 12 SP2 64 位(GNOME 版本3.20.2)

    SUSE Linux安装 apache 命令:sudo zypper in apache 设置apache 服务可用 命令:sudo systemctl enable apache2.service启 ...