传送门

题意:自己去看


考虑二分答案。$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. 【Java入门提高篇】Day27 Java容器类详解(九)LinkedList详解

    这次介绍一下List接口的另一个践行者——LinkedList,这是一位集诸多技能于一身的List接口践行者,可谓十八般武艺,样样精通,栈.队列.双端队列.链表.双向链表都可以用它来模拟,话不多说,赶 ...

  2. mysql索引类型 normal, unique, full text

    问题1:mysql索引类型normal,unique,full text的区别是什么? normal:表示普通索引 unique:表示唯一的,不允许重复的索引,如果该字段信息保证不会重复例如身份证号用 ...

  3. [20170825]不启动监听远程能连接数据库吗2.txt

    [20170825]不启动监听远程能连接数据库吗2.txt --//曾经写过一篇不启动监听连接数据库的帖子:http://blog.itpub.net/267265/viewspace-1816211 ...

  4. 洗礼灵魂,修炼python(37)--面向对象编程(7)—了解魔法方法

    也许上一篇博文提到的property内置函数的用法你还觉得记忆犹新,那么有没有更多的类似的方法呢?有的,就是本篇文章要说的魔法方法 魔法方法 1.什么是魔法方法 (其实前面已经提到多次,每次我都是说暂 ...

  5. Sql 查询结果 根据某个字段值 变更另外一个字段值 case when

    SELECT CASE THEN '*******' ELSE Plate END AS Plate, CarType FROM Cars;

  6. macOS 下NFS 文件系统挂载

    主要有两种方式: 使用:resvport选项, mount 挂载命令时. 使用:insecure选项, exportfs 文件配置时. sudo mount -o resvport IP:Addr b ...

  7. oracle启动的三个阶段

    startup nomount 时,数据库状态为 started; alter database mount 时, 状态为 mounted; alter database open 时,状态为 ope ...

  8. xunit-ICollectionFixture

      https://github.com/dmetzgar/dotnetcoreinaction

  9. 对haproxy文件进行增删改查

    1.文件内容 global log 127.0.0.1 local2 daemon maxconn 256 log 127.0.0.1 local2 info defaults log global ...

  10. Vue、Vuex+Cookie 实现自动登陆 。

    概述 1.自动登陆实现思路. 2.vuex + cookie 多标签页状态保持. 自动登陆的需求: 1.登陆时勾选自动登陆,退出登陆或登陆到期后再次登陆后自动填写表单(记住密码)或访问登陆页自动登陆. ...