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/Dijstra一遍得到每个点到每个门到最短距离。
考虑随着时间的推移,每个点能够到达的门也就越多,所以可以说是动态加边。
这时的正确方法是二分答案,建图网络流。
显然是源点连人,在时间允许的情况下人连门,容量为1。门连汇点,容量为T。
这样做理论上是很好的,但是有一个问题,那就是本题的特殊性,每个格子可以重复走人但是门只能一个一个出。
这就十分不和谐了,因为上面的做法并不能处理两个人同时到达的情况。
考虑一个问题,到底是什么性质没有被体现导致建图瑕疵。
这里可以认为门在T时刻关闭,那么本质上每个人都有一个剩余时间,假如说一起到然后一个一个出,
这里的问题就是假如说一起到的人比较多,假如说大于T那么一定不能全部出去。
所以需要有一个条件来限制每个人到达时还剩多少时间,换句话说,需要表现他究竟是什么时间到达的。
这样,将每个门拆成T个点,代表该时刻到达的门(相当于给门分层)。
每个点向到达时间的门连边,每层门向下一层连流量为$inf$的边。
跑最大流验证就好了。
代码:
 #include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
const int oo=0x3f3f3f3f;
struct int_2{int TIME;int NO;};
struct pnt{
int hd;
int lyr;
int now;
}p[];
struct ent{
int twd;
int vls;
int lst;
int his;
}e[];
struct OVO{
int_2 pro;
int i;
int j;
};
int cnt;
int n,m;
int s,t;
int pnum;
char tmp[];
int no[][];
int mp[][];
bool vis[][];
bool hvv[][];
std::queue<int>Q;
std::queue<OVO>P;
std::vector<int>T[];
std::vector<int_2>dr[][];
void ade(int f,int t,int v)
{
cnt++;
e[cnt].twd=t;
e[cnt].vls=v;
e[cnt].his=v;
e[cnt].lst=p[f].hd;
p[f].hd=cnt;
return ;
}
bool bfs(void)
{
for(int i=;i<=n;i++)
{
for(int j=;j<=m;j++)
{
if(mp[i][j]==)
{
while(!P.empty())
P.pop();
P.push((OVO){(int_2){,no[i][j]},i,j});
while(!P.empty())
{
OVO x=P.front();
P.pop();
int ii=x.i;
int jj=x.j;
if(vis[ii][jj])
continue;
vis[ii][jj]=true;
if(mp[ii][jj]==)
dr[ii][jj].push_back(x.pro);
x.pro.TIME++;
OVO y;
y=x;
y.i++;
if(y.i<=n)
{
if(mp[y.i][y.j]==)
{
P.push(y);
}
}
y=x;
y.i--;
if(y.i>)
{
if(mp[y.i][y.j]==)
{
P.push(y);
}
}
y=x;
y.j++;
if(y.j<=m)
{
if(mp[y.i][y.j]==)
{
P.push(y);
}
}
y=x;
y.j--;
if(y.j>)
{
if(mp[y.i][y.j]==)
{
P.push(y);
}
}
}
for(int ii=;ii<=n;ii++)
{
for(int jj=;jj<=m;jj++)
{
if(vis[ii][jj])
hvv[ii][jj]=true;
vis[ii][jj]=false;
}
}
}
}
}
for(int i=;i<=n;i++)
{
for(int j=;j<=m;j++)
{
if(!hvv[i][j]&&mp[i][j]==)
return true;
}
}
return false;
}
bool Bfs(void)
{
while(!Q.empty())Q.pop();
for(int i=;i<=t;i++)
p[i].lyr=;
p[s].lyr=;
Q.push(s);
while(!Q.empty())
{
int x=Q.front();
Q.pop();
for(int i=p[x].hd;i;i=e[i].lst)
{
int to=e[i].twd;
if(p[to].lyr==&&e[i].vls>)
{
p[to].lyr=p[x].lyr+;
if(to==t)
return true;
Q.push(to);
}
}
}
return false;
}
int Dfs(int x,int fll)
{
if(x==t)
return fll;
for(int& i=p[x].now;i;i=e[i].lst)
{
int to=e[i].twd;
if(p[to].lyr==p[x].lyr+&&e[i].vls>)
{
int ans=Dfs(to,std::min(fll,e[i].vls));
if(ans>)
{
e[i].vls-=ans;
e[((i-)^)+].vls+=ans;
return ans;
}
}
}
return ;
}
int Dinic(void)
{
int ans=;
while(Bfs())
{
for(int i=;i<=t;i++)
p[i].now=p[i].hd;
int dlt;
while(dlt=Dfs(s,oo))
ans+=dlt;
}
return ans;
}
bool Check(int x)
{
for(int i=;i<=t;i++)
p[i].hd=;
cnt=;
int lcnt=n*m;
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
if(mp[i][j]==)
{
T[no[i][j]].clear();
for(int k=;k<=x;k++)
T[no[i][j]].push_back(++lcnt);
}
s=lcnt+;
t=s+;
for(int i=;i<=n;i++)
{
for(int j=;j<=m;j++)
{
if(mp[i][j]==)
{
ade(s,no[i][j],);
ade(no[i][j],s,);
for(int k=;k<dr[i][j].size();k++)
{
if(dr[i][j][k].TIME<=x)
{
ade(no[i][j],T[dr[i][j][k].NO][dr[i][j][k].TIME],);
ade(T[dr[i][j][k].NO][dr[i][j][k].TIME],no[i][j],);
}
}
}else if(mp[i][j]==)
{
for(int k=;k<=x;k++)
{
ade(T[no[i][j]][k],t,);
ade(t,T[no[i][j]][k],);
if(k!=x)
{
ade(T[no[i][j]][k],T[no[i][j]][k+],oo);
ade(T[no[i][j]][k+],T[no[i][j]][k],);
}
}
}
}
}
return pnum==Dinic();
}
int main()
{
// freopen("a.in","r",stdin);
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)
{
scanf("%s",tmp+);
for(int j=;j<=m;j++)
{
no[i][j]=++cnt;
if(tmp[j]=='X')
mp[i][j]=;
if(tmp[j]=='.')
mp[i][j]=,
pnum++;
if(tmp[j]=='D')
mp[i][j]=;
}
}
cnt=;
if(bfs())
{
puts("impossible");
return ;
}
int l=,r=;
int ans;
while(l<=r)
{
int mid=(l+r)>>;
if(Check(mid))
{
ans=mid;
r=mid-;
}else
l=mid+;
}
printf("%d\n",ans);
return ;
}

BZOJ1189: [HNOI2007]紧急疏散evacuate(二分答案,最大流)的更多相关文章

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

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

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

    [BZOJ1189]紧急疏散(二分答案,最大流) 题面 Description 发生了火警,所有人员需要紧急疏散!假设每个房间是一个N M的矩形区域.每个格子如果是'.',那么表示这是一块空地:如果是 ...

  3. Bzoj1189 [HNOI2007]紧急疏散evacuate

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

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

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

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

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

  6. 【枚举】【二分答案】【分块答案】【BFS】【最大流】【Dinic】bzoj1189 [HNOI2007]紧急疏散evacuate

    [法一]枚举Time(0~N*M): S->'.'(1); 'D'->T(Time); '.'->'D'(dis(用BFS预处理,注意一旦到达'D',BFS就不能继续扩展了,注意di ...

  7. 洛谷 P3191 [HNOI2007]紧急疏散EVACUATE(网络最大流)

    题解 二分答案+Dinic最大流 二分答案\(mid\) 把门拆成\(mid\)个时间点的门 相邻时间的门连一条\(inf\)的边 预处理出每个门到每个人的最短时间 为\(dis[k][i][j]\) ...

  8. BZOJ1189:[HNOI2007]紧急疏散EVACUATE(最大流,枚举)

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

  9. BZOJ1189 [HNOI2007]紧急疏散evacuate 【二分 + 网络流】

    题目 发生了火警,所有人员需要紧急疏散!假设每个房间是一个N M的矩形区域.每个格子如果是'.',那么表示这是一 块空地:如果是'X',那么表示这是一面墙,如果是'D',那么表示这是一扇门,人们可以从 ...

随机推荐

  1. 洛谷——P3370 【模板】字符串哈希

    题目描述 如题,给定N个字符串(第i个字符串长度为Mi,字符串内包含数字.大小写字母,大小写敏感),请求出N个字符串中共有多少个不同的字符串. 友情提醒:如果真的想好好练习哈希的话,请自觉,否则请右转 ...

  2. [MST] Derive Information from Models Using Views

    Redundant data or caching data is a constant source of bugs. MST adheres to the philosophy that no d ...

  3. 生成apk文件遇到的编译问题error: format not a string literal and no format arguments

    编译错误时使用的android-ndk为r9的版本号.报下面错误: "Compile++ thumb : cocosdenshion_static <= SimpleAudioEngi ...

  4. Vue源代码笔记(一)数据绑定

    VUE数据绑定介绍 数据绑定是vue的基础核心之一,本文以Vue对象(当然也包含VueComponent)里的data数据绑定为例,阐述整个绑定的过程. Vue的数据绑定由三部分组成, Observe ...

  5. springboot Ehcache缓存配置

    例牌的导包 <!-- 包含支持UI模版(Velocity,FreeMarker,JasperReports), 邮件服务, 脚本服务(JRuby), 缓存Cache(EHCache), 任务计划 ...

  6. 8.queue

    #include <iostream> #include <stack> #include <algorithm> #include <list> #i ...

  7. Metasploit的三种启动方式

    不多说,直接上干货! 注意:博主我用的是Kali linux 2016.2(Rolling).  msfcli 的启动 root@kali:~# msfcli -h bash: msfcli: 未找到 ...

  8. 关于ListView的一些不常用到的属性

    1.setCacheColorHint自定义listview的时候,当你不使用Android:cacheColorHint=“#00000000”会出现下面选中一个空间黑色底色的情况,破坏整体美观度 ...

  9. UI Framework-1: Aura Gesture Recognizer

    Gesture Recognizer Gesture Recognizer Overview This document describes the process by which Touch Ev ...

  10. Display Video

    ###chromium webrtc视频显示 ###两个数据源:本地数据源: MediaStreamRemoteVideoSource(content/renderer/media/webrtc/me ...