博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【BZOJ1189】紧急疏散(二分答案,最大流)
阅读量:4318 次
发布时间:2019-06-06

本文共 2994 字,大约阅读时间需要 9 分钟。

【BZOJ1189】紧急疏散(二分答案,最大流)

题面

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

题解

首先预处理出来每个空位置到每个门的距离

然而很容易想到二分一个时间
现在考虑如何建图
首先,如果距离小于给定的时间就可以走到门
那么,就从每个空位连向门就行啦?

当然不行

这样子做就不能达到每秒钟只能出去一个人的限制
所以,拆点
把门拆成时间个
当前点哪个时间到达就连接在那个时间上
同时,每个节点连一个容量为1的边到汇点上表示出去了
因为前面的人是可以留在门口等到接下来再出去
所以从每个拆开的门向下一秒连一个容量为INF的边

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;#define MAXL 5000000#define MAX 100000#define __ 40#define INF 1000000000inline int read(){ int x=0,t=1;char ch=getchar(); while((ch<'0'||ch>'9')&&ch!='-')ch=getchar(); if(ch=='-')t=-1,ch=getchar(); while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar(); return x*t;}struct Line{ int v,next,w;}e[MAXL];int h[MAX],cnt;int S,T,n,m,K;inline void Add(int u,int v,int w){ e[cnt]=(Line){v,h[u],w};h[u]=cnt++; e[cnt]=(Line){u,h[v],0};h[v]=cnt++;}int level[MAX];bool BFS(){ memset(level,0,sizeof(level)); level[S]=1; queue
Q; Q.push(S); while(!Q.empty()) { int u=Q.front();Q.pop(); for(int i=h[u];i!=-1;i=e[i].next) { int v=e[i].v; if(e[i].w&&!level[v]) level[v]=level[u]+1,Q.push(v); } } return level[T];}int DFS(int u,int flow){ if(flow==0||u==T)return flow; int ret=0; for(int i=h[u];i!=-1;i=e[i].next) { int v=e[i].v; if(e[i].w&&level[v]==level[u]+1) { int dd=DFS(v,min(flow,e[i].w)); flow-=dd;ret+=dd; e[i].w-=dd;e[i^1].w+=dd; } } return ret;}int Dinic(){ int ret=0; while(BFS())ret+=DFS(S,INF); return ret;}int tot,blk;int qx[MAX],qy[MAX],dr;int d[4][2]={0,1,1,0,-1,0,0,-1};char g[__][__];int b[__][__],dd[__][__],dis[__*__][__*__];bool vis[__][__];void Getdis(int K,int x,int y){ memset(vis,0,sizeof(vis)); queue
Qx,Qy; memset(dis[K],63,sizeof(dis[K])); Qx.push(x),Qy.push(y);vis[x][y]=true;dis[K][b[x][y]]=0; while(!Qx.empty()) { int u=Qx.front(),v=Qy.front(); Qx.pop();Qy.pop(); for(int i=0;i<4;++i) { int xx=u+d[i][0],yy=v+d[i][1]; if(vis[xx][yy])continue; vis[xx][yy]=true; if(x&&y&&x<=n&&y<=m&&g[xx][yy]=='.') { dis[K][b[xx][yy]]=dis[K][b[u][v]]+1; Qx.push(xx);Qy.push(yy); } } }}int tt[500];void Build(int K){ memset(h,-1,sizeof(h));cnt=0; S=0;T=50000; for(int i=1;i<=n;++i) for(int j=1;j<=m;++j) if(g[i][j]=='.')Add(S,b[i][j],1); int bh=n*m; for(int gg=1;gg<=dr;++gg) { for(int i=1;i<=K;++i)tt[i]=++bh; for(int i=1;i
>1; Build(mid); if(Dinic()==blk)ans=mid,r=mid-1; else l=mid+1; } ans>=1e9?puts("impossible"):printf("%d\n",ans); return 0;}

转载于:https://www.cnblogs.com/cjyyb/p/8214245.html

你可能感兴趣的文章
sk_buff Structure
查看>>
oracle的级联更新、删除
查看>>
多浏览器开发需要注意的问题之一
查看>>
Maven配置
查看>>
HttpServletRequest /HttpServletResponse
查看>>
SAM4E单片机之旅——24、使用DSP库求向量数量积
查看>>
从远程库克隆库
查看>>
codeforces Unusual Product
查看>>
hdu4348 - To the moon 可持久化线段树 区间修改 离线处理
查看>>
springMVC中一个class中的多个方法
查看>>
Linux系统安装出错后出现grub rescue的修复方法
查看>>
线段树模板整理
查看>>
[教程][6月4日更新]VMware 8.02虚拟机安装MAC lion 10.7.3教程 附送原版提取镜像InstallESD.iso!...
查看>>
[iOS问题归总]iPhone上传项目遇到的问题
查看>>
Python天天美味(总) --转
查看>>
Spring Framework tutorial
查看>>
【VS开发】win7下让程序默认以管理员身份运行
查看>>
【机器学习】Learning to Rank 简介
查看>>
Unity 使用实体类
查看>>
【转】通过文件锁实现,程序开始运行时,先判断文件是否存在,若存在则表明该程序已经在运行了,如果不存在就用open函数创建该文件,程序退出时关闭文件并删除文件...
查看>>