传送门

题意:自己去看


考虑二分答案。$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. Linux环境下运行简单java程序

    一.安装java 1.下载jdk8 登录网址:http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-213315 ...

  2. 在Visualforce页面中使用Visual Flow

    在本文中,我们将通过一个示例说明如何将"流"(Visual Flow)用于Visualforce页面. 更全面的知识可以参考官方文档. 创建流 我们要创建一个流,它的作用是得到一个 ...

  3. JMeter 查看结果树监听器响应数据中文显示乱码解决方法

    查看结果树监听器响应数据中文显示乱码解决方法 by:授客 QQ:1033553122   问题描述 使用监听器-查看结果树(View Results Tree Listener)过程中发现,响应数据面 ...

  4. loadrunner 场景设计-设置结果文件保存路径

    场景设计-设置结果文件保存路径 by:授客 QQ:1033553122 Results->Results settings Results Name 结果文件夹名称 Directory 指定结果 ...

  5. 《Inside C#》笔记(十一) 运算符重载

    运算符重载与之前的索引器类似,目的是为了让语言本身使用起来更方便直接,也是一种语法糖. 一 运算符重载(Operator Overloading) 运算符重载的存在,使得现有的各种运算符可以被重新定义 ...

  6. MySQL——优化嵌套查询和分页查询

    优化嵌套查询 嵌套查询(子查询)可以使用SELECT语句来创建一个单列的查询结果,然后把这个结果作为过滤条件用在另一个查询中.嵌套查询写起来简单,也容易理解.但是,有时候可以被更有效率的连接(JOIN ...

  7. drop all database objects

    /*Use this sql to drop all objects in a database.*/ -- Drop all SPdeclare @dropSp varchar(max)=''sel ...

  8. Java动态生成类以及动态添加属性

    有个技术实现需求:动态生成类,其中类中的属性来自参数对象中的全部属性以及来自参数对象properties文件. 那么技术实现支持:使用CGLib代理. 具体的实现步骤: 1.配置Maven文件: &l ...

  9. EasyUI datagrid.getSelections 没有返回正确的选择行数

    Actually i solved the problem. It was because the idField of the table i was using was incorrect. it ...

  10. 分布式文件系统(HDFS)与 linux系统文件系统 对比

    初次接触分布式文件系统,有很多迷惑.通过参考网络文章,这里进行对比一下Hadoop 分布式文件系统(HDFS)与 传统文件系统之间的关系:   Linux 文件系统 分布式文件系统 块 块对应物理磁盘 ...