传送门

题意:自己去看


考虑二分答案。$BFS$预处理出每一个人到每一扇门的最短时间,设二分的值为$mid$,那么把门拆成$mid$个点,每一个点代表第$1,2,...,mid$秒时的状态。$i-1$时刻的门向$i$时刻的门连一条流量为$INF$的边,表示有无限多的人可以在门口等待。每一个门拆出来的$mid$个点向汇点连流量为$1$的边表示逃出的一个人;源点向每一个人连一条流量为$1$的边,每一个人对应的点向每一扇门的最早到达时刻对应的点连一条流量为$1$的边,最后计算最大流是否等于人数即可。

 #include<bits/stdc++.h>
#define MAXN 7010
#define XX now.x + dir[i][0]
#define YY now.y + dir[i][1]
#define INF 0x7fffffff
using namespace std; struct Edge{
int end , upEd , flow;
}Ed[MAXN << ];
struct node{
int x , y , flo;
}now;
const int dir[][] = {,,,-,,,-,};
int head[MAXN] , flo[MAXN] , cur[MAXN] , cntEd , cntBlock , N , M , cntDoor , dis[][] , mid;
map < pair < int , int > , int > door;
char c[][];
bool vis[][] , be[MAXN];
queue < int > q1;
queue < node > q2; void bfs(int x , int y){
cntBlock++;
memset(dis[cntBlock] , 0x3f , sizeof(dis[cntBlock]));
q2.push((node){x , y , });
memset(vis , , sizeof(vis));
vis[x][y] = ;
while(!q2.empty()){
now = q2.front();
q2.pop();
for(int i = ; i < ; i++)
if(c[XX][YY] != 'X' && !vis[XX][YY]){
vis[XX][YY] = ;
if(c[XX][YY] == 'D')
dis[cntBlock][door.find(make_pair(XX , YY))->second] = now.flo + ;
else
q2.push((node){XX , YY , now.flo + });
}
}
} bool div(){
while(!q1.empty())
q1.pop();
memset(be , , sizeof(be));
q1.push();
be[] = flo[] = ;
while(!q1.empty()){
int t = q1.front();
q1.pop();
for(int i = head[t] ; i ; i = Ed[i].upEd){
if(!be[Ed[i].end] && Ed[i].flow){
flo[Ed[i].end] = flo[t] + ;
be[Ed[i].end] = ;
if(Ed[i].end == cntBlock + cntDoor * mid + ){
memcpy(cur , head , sizeof(head));
return ;
}
q1.push(Ed[i].end);
}
}
}
return ;
} bool dinic(int now){
if(now == cntBlock + cntDoor * mid + )
return ;
for(int &i = cur[now] ; i ; i = Ed[i].upEd)
if(flo[Ed[i].end] == flo[now] + && Ed[i].flow)
if(dinic(Ed[i].end)){
Ed[i].flow--;
Ed[i ^ ].flow++;
return ;
}
return ;
} inline void addEd(int a , int b , int c){
Ed[++cntEd].end = b;
Ed[cntEd].flow = c;
Ed[cntEd].upEd = head[a];
head[a] = cntEd;
} bool check(){
memset(head , , sizeof(head));
cntEd = ;
int T = cntDoor * mid + cntBlock + ;
for(int i = ; i < cntDoor ; i++)
for(int j = ; j < mid ; j++){
addEd(mid * i + j + cntBlock , mid * i + j + cntBlock + , INF);
addEd(mid * i + j + cntBlock + , mid * i + j + cntBlock , );
}
for(int i = ; i < cntDoor ; i++)
for(int j = ; j <= mid ; j++){
addEd(mid * i + j + cntBlock , T , );
addEd(T , mid * i + j + cntBlock , );
}
int cnt = ;
for(int i = ; i < N ; i++)
for(int j = ; j < M ; j++)
if(c[i][j] == '.'){
cnt++;
for(int k = ; k <= cntDoor ; k++)
if(dis[cnt][k] <= mid){
addEd(cnt , mid * (k - ) + dis[cnt][k] + cntBlock , );
addEd(mid * (k - ) + dis[cnt][k] + cntBlock , cnt , );
}
addEd( , cnt , );
addEd(cnt , , );
}
int ans = ;
while(div())
while(dinic())
ans++;
return ans == cntBlock;
} int main(){
cin >> N >> M;
for(int i = ; i <= N ; i++)
for(int j = ; j <= M ; j++){
cin >> c[i][j];
if(c[i][j] == 'D')
door.insert(make_pair(make_pair(i , j) , ++cntDoor));
}
for(int i = ; i < N ; i++)
for(int j = ; j < M ; j++)
if(c[i][j] == '.')
bfs(i , j);
int L = , R = N * M;
while(L < R){
mid = L + R >> ;
check() ? R = mid : L = mid + ;
}
if(R == N * M)
cout << "impossible";
else
cout << R;
return ;
}

Luogu3191 HNOI2007 紧急疏散 二分答案、最大流的更多相关文章

  1. BZOJ 1570: [JSOI2008]Blue Mary的旅行( 二分答案 + 最大流 )

    二分答案, 然后对于答案m, 把地点分成m层, 对于边(u, v), 第x层的u -> 第x+1层的v 连边. 然后第x层的u -> 第x+1层的u连边(+oo), S->第一层的1 ...

  2. BZOJ 1738: [Usaco2005 mar]Ombrophobic Bovines 发抖的牛( floyd + 二分答案 + 最大流 )

    一道水题WA了这么多次真是.... 统考终于完 ( 挂 ) 了...可以好好写题了... 先floyd跑出各个点的最短路 , 然后二分答案 m , 再建图. 每个 farm 拆成一个 cow 点和一个 ...

  3. BZOJ 1305 CQOI2009 dance跳舞 二分答案+最大流

    题目大意:给定n个男生和n个女生,一些互相喜欢而一些不.举行几次舞会,每次舞会要配成n对.不能有同样的组合出现.每一个人仅仅能与不喜欢的人跳k次舞,求最多举行几次舞会 将一个人拆成两个点.点1向点2连 ...

  4. HDU3081(KB11-N 二分答案+最大流)

    Marriage Match II Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others ...

  5. BZOJ2547 CTSC2002玩具兵(最短路径+二分答案+最大流)

    先不考虑只有一个显得有些特殊的天兵. 可以发现超能力的作用实质上是使兵更换职业.每一个兵到达某个位置最少需要更换职业的次数是彼此独立的,因为如果需要某两人互换职业可以使他们各自以当前职业到达需要到的地 ...

  6. Gym - 101908G 二分答案+最大流

    After the end of the truck drivers' strike, you and the rest of Nlogônia logistics specialists now h ...

  7. 「LuoguP3191」 [HNOI2007]紧急疏散EVACUATE(最大流

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

  8. 紫书 习题 11-10 UVa 12264 (二分答案+最大流)

    书上写的是UVa 12011, 实际上是 12264 参考了https://blog.csdn.net/xl2015190026/article/details/51902823 这道题就是求出一种最 ...

  9. luoguP1401 城市(二分答案+最大流)

    题意 N(2<=n<=200)个城市,M(1<=m<=40000)条无向边,你要找T(1<=T<=200)条从城市1到城市N的路,使得最长的边的长度最小,边不能重复 ...

随机推荐

  1. 【读书笔记】iOS-优化内存

    imageNamed:方法创建UIImage对象,这些对象不再使用的时候 会放到应用的默认自动回收池中,而不是当前的事件循环的自动回收池中,这样的对象占用的内存只有在应用结束的时候 才会回收.如果用这 ...

  2. JAVA 和.NET在安全功能的比较

    以下转载于: http://www.it28.cn/ASPNET/825159.html 本文根据Denis Piliptchouk的文章翻译.摘录而来,有些术语翻译不太好理解,还请参考原文. 第一部 ...

  3. JMeter Sampler之BeanShellSampler的使用

    Sampler之BeanShellSampler的使用 by:授客 QQ:1033553122 欢迎加入软件性能测试交流群:7156436 1.  Bean Shell简介 ·         Bea ...

  4. loadrunner 运行场景-场景运行原理

    运行场景-场景运行原理 by:授客 QQ:1033553122 运行原理 1 Remote Agent Dispatcher(Process) 运行Controller在负载机上开启应用程序. 2  ...

  5. (网页)JS和CSS不缓存方法,时间戳

    <link ..... href=".....css?time"+new Date()> <script type="text/javascript&q ...

  6. Python之groupby

    # -*- coding: utf-8 -*-"""Created on Sat Jun 30 10:09:47 2018测试分组groupby@author: zhen ...

  7. 安装office2010提示要安装MSXML6.10.1129.0解决方法

    系统win7 32位 安装office2010出现了错误,提示要安装MSXML6.10.1129.0解决方法 1.下载MSXML6.10.1129.0进行安装 2.若本机已安装过不管用: a.在运行里 ...

  8. WPF:验证登录后关闭登录窗口,显示主窗口的解决方法

    http://www.27ba.com/post/145.html WPF:验证登录后关闭登录窗口,显示主窗口的解决方法 最近想做一个基于Socket的通讯工具,想模仿QQ那样,需要先登录,登录成功后 ...

  9. Dos烧录脚本

    Dos命令之前更改的太简单,现在加入判断是否进入fasboot模式和判断Android镜像是否存在:代码已经尽量简化成这样,dos命令功能还是比较不好用的,用了一下午的时间... @echo off ...

  10. iOS 多线程之GCD的简单使用

    在iOS开发中,遇到耗时操作,我们经常用到多线程技术.Grand Central Dispatch (GCD)是Apple开发的一个多核编程的解决方法,只需定义想要执行的任务,然后添加到适当的调度队列 ...