题目链接
sb错误调了3hour+。。
bfs预处理出每个\(.\)到每个\(D\)的最短距离。
二分时间\(t\),把每个\(D\)拆成\(t\)个点,这\(t\)个点两两连边,流量\(INF\)表示\(t\)个时刻都可以从这个\(D\)出。
然后枚举所有\(.\),再枚举所有\(D\),如果距离\(dis\)小于\(t\),就从这个\(.\)向这个\(D\)的第\(dis\)个点连一条流量为\(1\)的边,表示从这个时刻开始这个\(.\)可以从这个\(D\)出。
然后求最大流,如果等于\(.\)的个数,说明此\(t\)可行,二分一下即可。

#include <cstdio>
#include <queue>
#include <cstdlib>
#include <cstring>
#define INF 2147483647
using namespace std;
const int MAXN = 300010;
const int N = 440;
const int MAXM = 200010;
char a[N][N];
int b[N][N], c[N][N];
struct point{int x, y, time;
}Now;
queue <int> q;
queue <point> Q;
struct Edge{int from, to, next, rest;
}e[MAXM];
int head[MAXN], num = 1, s, t, now, n, m, dis[MAXN];
inline void Add(int from, int to, int flow){e[++num] = (Edge){ from, to, head[from], flow }; head[from] = num;e[++num] = (Edge){ to, from, head[to], 0 }; head[to] = num;
}
inline int id(int i, int j){return (i - 1) * m + j;
}
int re(){memset(dis, 0, sizeof dis);q.push(s); dis[s] = 1;while(q.size()){now = q.front(); q.pop();for(int i = head[now]; i; i = e[i].next)if(e[i].rest && !dis[e[i].to])dis[e[i].to] = dis[now] + 1, q.push(e[i].to);}return dis[t];
}
int find(int u, int flow){if(u == t || !flow) return flow;/*if(u == 448){int xsxs = 1;}*/int sum = 0, T;for(int i = head[u]; i; i = e[i].next)if(e[i].rest && dis[e[i].to] == dis[u] + 1){T = find(e[i].to, min(flow - sum, e[i].rest));e[i].rest -= T; e[i ^ 1].rest += T; sum += T;}if(!sum) dis[u] = 0;return sum;
}
int dinic(){int ans = 0;while(re()) ans += find(s, INF);/*for(int i = 1; i <= num; ++i)if(e[i].to <= n * m && e[i].from == s)if(e[i].rest)printf("%d %d %d\n", (e[i].to - 1) / 12 + 1, e[i].to % 12 == 0 ? 12 : e[i].to % 12, e[i].to);system("pause");*/return ans;
}
int cnt, tot, l[] = {233, -1, 1, 0, 0}, r[] = {666, 0, 0, -1, 1}, vis[N][N], L, R;
void bfs(int x, int y){Q.push((point){x, y, 0});for(int i = 1; i <= n; ++i)for(int j = 1; j <= m; ++j)vis[i][j] = 0;vis[x][y] = 1;while(Q.size()){Now = Q.front(); Q.pop();for(int i = 1; i <= 4; ++i){int X = Now.x + l[i], Y = Now.y + r[i];if(!X || !Y || X > n || Y > m || a[X][Y] == 'X' || vis[X][Y]) continue;Q.push((point){X, Y, Now.time + 1});vis[X][Y] = 1;if(b[X][Y]) c[id(x, y)][b[X][Y]] = Now.time + 1;}}
}
int ans, mid;
int main(){scanf("%d%d", &n, &m); s = 290000; t = 300001;for(int i = 1; i <= n; ++i)scanf("%s", a[i] + 1);for(int i = 1; i <= n; ++i)for(int j = 1; j <= m; ++j)if(a[i][j] == 'D')b[i][j] = ++cnt;else if(a[i][j] == '.')++tot;for(int i = 1; i <= n; ++i)for(int j = 1; j <= m; ++j)if(a[i][j] == '.')bfs(i, j);L = 1; R = 400; ans = -1;if(tot)while(L <= R){mid = (L + R) >> 1;memset(head, 0, sizeof head);num = 1;for(int i = 1; i <= n; ++i)for(int j = 1; j <= m; ++j)if(a[i][j] == '.'){Add(s, id(i, j), 1);for(int k = 1; k <= cnt; ++k){int d = id(i, j);if(c[d][k] && c[d][k] <= mid)Add(d, 400 + cnt * c[d][k] + k, 1);}}for(int i = 1; i <= cnt; ++i)for(int j = 1; j <= mid; ++j)Add(400 + cnt * j + i, t, 1), Add(400 + cnt * j + i, 400 + cnt * j + cnt + i, INF);if(dinic() == tot) ans = mid, R = mid - 1;else L = mid + 1;}if(ans == -1) printf("impossible\n");else printf("%d\n", ans);return 0;
}

转载于:https://www.cnblogs.com/Qihoo360/p/10539447.html

【洛谷 P3191】 [HNOI2007]紧急疏散EVACUATE(二分答案,最大流)相关推荐

  1. 洛谷P1462 通往奥格瑞玛的道路 二分答案+最短路SPFA

    洛谷P1462 通往奥格瑞玛的道路 二分答案+最短路SPFA 二分交费最多的一次的钱数 然后只将符合要求的边加入图中 如果到终点的最短路大于等于血量 或者直接起点不能到达终点 那么说明不符合要求 需要 ...

  2. 洛谷3933 Chtholly Nota Seniorious 二分答案+贪心

    题目链接 题意 给你一个N*M的矩阵 (N,M <=2000)  把他分成两部分 使两部分的极差较大的一个最小  求这个最小值.然后分矩阵的要求是:每个部分内部的方块之间,可以通过上下左右相互到 ...

  3. 洛谷 P1824 进击的奶牛 【二分答案】(求最大的最小值)

    题目链接:https://www.luogu.org/problemnew/show/P1824 题目描述 Farmer John建造了一个有N(2<=N<=100,000)个隔间的牛棚, ...

  4. 洛谷P1902 刺杀大使(二分答案+bfs验证)

    题目描述 伊朗伊斯兰革命卫队(某恐怖组织)正在策划一起刺杀行动,他们的目标是沙特驻美大 使朱拜尔.他们来到了沙特驻美使馆,准备完成此次刺杀,要进入使馆首先必须通过使馆前 的防御迷阵. 迷阵由 n*m ...

  5. [洛谷1462 ]通往奥格瑞玛的道路---二分答案+spfa

    题目背景 在艾泽拉斯大陆上有一位名叫歪嘴哦的神奇术士,他是部落的中坚力量 有一天他醒来后发现自己居然到了联盟的主城暴风城 在被众多联盟的士兵攻击后,他决定逃回自己的家乡奥格瑞玛 题目描述 在艾泽拉斯, ...

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

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

  7. bzoj1189 [HNOI2007]紧急疏散evacuate(二分答案+bfs+最大流判是否满流)

    首先bfs处理出每个人到每个门所需的时间.然后二分答案,对于所有人能到的所有门,建边,边权为1,从源点向所有人建边,边权为1,从所有门向汇点建边,边权为mid(最多出去mid个人),dinic跑最大流 ...

  8. 洛谷试炼场-简单数学问题-二分查找

    洛谷试炼场-简单数学问题 P1147 连续自然数和 题解: 本题给定一个数n,求连续自然数的和为n,用一个前缀数组,low_bound,upper_bound,查找是否是同一个数.O(nlog(n)) ...

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

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

  10. 河城荷取 二分答案 最大流

    NKOJ2507 河城荷取 问题描述 在幻想乡,河城荷取是擅长高科技工业的河童.荷取的得意之作除了光学迷彩外,还有震动整个幻想乡的巨型人形『非想天则』.不过由于人形太过巨大,所以为它充能是一件很麻烦的 ...

最新文章

  1. linux mysql 管理(转载)
  2. 解决Docker构建时出现的 WARNING: Ignoring https://dl-cdn.alpinelinux.org/alpine/v3.13/main: Permission denied
  3. 根据id获取多维数组路径_程序员的进阶课-架构师之路(2)-数组
  4. python 重定向stdout_Python 犄角旮旯--重定向 stdout
  5. 中raise抛出异常_Ruby 异常
  6. 网络间谍在2017年被列为全球企业最为严重的威胁
  7. python和大数据的关系_Java大数据和python大数据哪个更主流?
  8. 大学生创新项目管理系统
  9. build lavas 失败_构建配置 - Lavas 教程
  10. linux日期时间转换函数,Linux时间戳、日期转换函数
  11. c语言节点的作用,C语言试题
  12. 计算机硕士-工资一览表
  13. 关于es8316的音频爆破音的解决
  14. c#与python 交互(调用第三方库)
  15. 面向对象编程基本概念
  16. 3D打印机T3升级corexy  制作过程(二)
  17. 使用云效 修改 layui 环境变量
  18. MLDLRL:MLDL相关概念的原始英文解释——对理解最初的ML和DL的相关概念的定义非常有用
  19. 打印机设置为双面打印
  20. 全球及中国医用管材行业十四五产销需求趋势展望报告2021-2027年版

热门文章

  1. 为什么不带图发不了朋友圈?微信发朋友圈不带图片怎么发
  2. 使用spilt截取文件名后缀时出现的问题
  3. 世嘉rom_庆祝世嘉音响团队
  4. 排水管网信息系统、市政排水管网信息化智慧化管理
  5. MMDetection框架入门教程(完全版)
  6. 【Tpshop商城使用】
  7. VS Code:推荐插件 - HTML格式化(包括JS、CSS)
  8. 什么邮箱最好用?主流邮箱品牌如何选择
  9. 外贸邮箱能群发吗?用哪个外贸邮箱发开发信回复率高?
  10. pandas从excel导入数据,写入数据库