传送门

题意:自己去看


考虑二分答案。$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. python之继承

    1.经典MRO : 树形结构的深度遍历优先 - > 树形结构遍历 class A: pass class B(A): pass class C(A): pass class D(B, C): p ...

  2. 用css实现圆形波浪效果图

    在移动端经常看到一些圆形波浪图来显示金额,刚开始我认为这种效果只能用canvas写的,后来发现用css也可以. 原理:我们都知道让块元素的border-radius:50%会变成圆形,如果少于50%呢 ...

  3. Linux原理总结 。。。更新中

    问题: 1.32位和64位Linux系统的区别是什么? 答:64位系统CPU运行速度快,支持更大的内存,能够更好的发挥服务器硬件的性能,提高业务效率 2.描述Linux分区的知识(包括设备名.主分区. ...

  4. ionic打包报错Execution failed for task ':processDebugResources'

    ionic 打包的时候报了这样一个错误:Execution failed for task ':processDebugResources' 分析: compile "com.android ...

  5. Android 打开文件或文件夹777权限

    打开777权限 public class SystemManager extends Activity { public static boolean RootCommand(String comma ...

  6. onSaveInstanceState场景

    需要注意的是, onSaveInstanceState()方法并不是一定会被调用的, 因为有些场景是不需要保存状态数据的. 比如用户按下BACK键退出activity时, 用户显然想要关闭这个acti ...

  7. Spark性能优化(基于Spark 1.x)

    Task优化:    1.慢任务的性能优化:可以考虑减少每个Partition处理的数据量,同时建议开启spark.speculation(慢任务推导,当检测的慢任务时,会同步开启相同的新任务,谁先完 ...

  8. input输入的数据只允许整数和浮点型数据

    //第一步:引入jquery //第二步:input输入框绑定该函数 例如:<input type="text" name="price" onInput ...

  9. HTTP协议响应码及get请求和post请求比较

    HTTP协议响应码 1XX:信息响应类,表示接收到请求并且继续处理 2XX:处理成功响应类,表示动作被成功接受.理解和接受 200 OK:表示从客户端发来的请求在服务器端被正常处理了 204 No C ...

  10. 30个最常用的Linux系统命令行

    1.cd命令这是一个非常基本,也是大家经常需要使用的命令,它用于切换当前目录,它的参数是要切换到的目录的路径,可以是绝对路径,也可以是相对路径.如:cd /root/Docements # 切换到目录 ...