题目

发生了火警,所有人员需要紧急疏散!假设每个房间是一个N M的矩形区域。每个格子如果是'.',那么表示这是一

块空地;如果是'X',那么表示这是一面墙,如果是'D',那么表示这是一扇门,人们可以从这儿撤出房间。已知门

一定在房间的边界上,并且边界上不会有空地。最初,每块空地上都有一个人,在疏散的时候,每一秒钟每个人都

可以向上下左右四个方向移动一格,当然他也可以站着不动。疏散开始后,每块空地上就没有人数限制了(也就是

说每块空地可以同时站无数个人)。但是,由于门很窄,每一秒钟只能有一个人移动到门的位置,一旦移动到门的

位置,就表示他已经安全撤离了。现在的问题是:如果希望所有的人安全撤离,最短需要多少时间?或者告知根本

不可能。

输入格式

第一行是由空格隔开的一对正整数N与M,3<=N <=20,3<=M<=20,

以下N行M列描述一个N M的矩阵。其中的元素可为字符'.'、'X'和'D',且字符间无空格。

输出格式

只有一个整数K,表示让所有人安全撤离的最短时间,

如果不可能撤离,那么输出'impossible'(不包括引号)。

输入样例

5 5

XXXXX

X...D

XX.XX

X..XX

XXDXX

输出样例

3

题解

先bfs预处理每个点到各个出口的最短距离

二分一下时间\(t\),对出口拆点表示各个时间的出口

每个人向每个出口大于最短路的那些点连边

然后网络流判一下能否完全匹配即可

【坑点:角落的出口无法到达】

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cmath>
  4. #include<queue>
  5. #include<cstring>
  6. #include<algorithm>
  7. #define LL long long int
  8. #define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
  9. #define REP(i,n) for (int i = 1; i <= (n); i++)
  10. #define BUG(s,n) for (int i = 1; i <= (n); i++) cout<<s[i]<<' '; puts("");
  11. using namespace std;
  12. const int maxn = 300005,maxm = 6000005,INF = 1000000000;
  13. inline int read(){
  14. int out = 0,flag = 1; char c = getchar();
  15. while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
  16. while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
  17. return out * flag;
  18. }
  19. char s[25][25];
  20. int N,M,vis[25][25],id[25][25],now,X[] = {0,0,-1,1},Y[] = {-1,1,0,0};
  21. int n,m,dis[405][405],flag,S,T;
  22. int h[maxn],ne = 2;
  23. struct EDGE{int to,nxt,f;}ed[maxm];
  24. inline void build(int u,int v,int f){
  25. ed[ne] = (EDGE){v,h[u],f}; h[u] = ne++;
  26. ed[ne] = (EDGE){u,h[v],0}; h[v] = ne++;
  27. }
  28. struct point{int x,y,d;};
  29. void bfs(int x,int y){
  30. memset(vis,0,sizeof(vis));
  31. queue<point> q; q.push((point){x,y,0});
  32. point u; int nx,ny;
  33. while (!q.empty()){
  34. u = q.front(); q.pop();
  35. for (int k = 0; k < 4; k++){
  36. nx = u.x + X[k];
  37. ny = u.y + Y[k];
  38. if (nx < 1 || ny < 1 || nx > N || ny > M || s[nx][ny] == 'X' || vis[nx][ny])
  39. continue;
  40. vis[nx][ny] = true;
  41. if (s[nx][ny] == 'D') dis[id[x][y]][id[nx][ny]] = u.d + 1,flag = true;
  42. else q.push((point){nx,ny,u.d + 1});
  43. }
  44. }
  45. }
  46. int q[maxn],head,tail;
  47. int d[maxn],Vis[maxn],cur[maxn];
  48. bool bfs(){
  49. for (int i = S; i <= T; i++) d[i] = Vis[i] = 0;
  50. q[head = tail = 1] = S; Vis[S] = true;
  51. int u;
  52. while (head <= tail){
  53. u = q[head++];
  54. Redge(u) if (ed[k].f && !Vis[to = ed[k].to]){
  55. d[to] = d[u] + 1; Vis[to] = true;
  56. if (to == T) return true;
  57. q[++tail] = to;
  58. }
  59. }
  60. return Vis[T];
  61. }
  62. int dfs(int u,int minf){
  63. if (u == T || !minf) return minf;
  64. int flow = 0,f,to;
  65. if (cur[u] == -1) cur[u] = h[u];
  66. for (int& k = cur[u]; k; k = ed[k].nxt)
  67. if (d[to = ed[k].to] == d[u] + 1 && (f = dfs(to,min(minf,ed[k].f)))){
  68. ed[k].f -= f; ed[k ^ 1].f += f;
  69. flow += f; minf -= f;
  70. if (!minf) break;
  71. }
  72. return flow;
  73. }
  74. int maxflow(){
  75. int flow = 0;
  76. while (bfs()){
  77. for (int i = S; i <= T; i++) cur[i] = -1;
  78. flow += dfs(S,INF);
  79. }
  80. return flow;
  81. }
  82. bool check(int len){
  83. memset(h,0,sizeof(h));
  84. ne = 2; S = 0; T = n + m * len + 1;
  85. REP(i,n){
  86. build(S,i,1);
  87. REP(j,m){
  88. for (int k = dis[i][j]; k <= len; k++)
  89. build(i,n + (j - 1) * len + k,1);
  90. }
  91. }
  92. REP(i,m) REP(j,len) build(n + (i - 1) * len + j,T,1);
  93. int t = maxflow();
  94. return t == n;
  95. }
  96. int main(){
  97. N = read(); M = read();
  98. REP(i,N){
  99. scanf("%s",s[i] + 1);
  100. REP(j,M){
  101. if (s[i][j] == '.') id[i][j] = ++n;
  102. if (s[i][j] == 'D') id[i][j] = ++m;
  103. }
  104. }
  105. REP(i,n) REP(j,m) dis[i][j] = INF;
  106. REP(i,N) REP(j,M){
  107. if (s[i][j] == '.'){
  108. flag = false;
  109. bfs(i,j);
  110. if (!flag) {
  111. puts("impossible");
  112. return 0;
  113. }
  114. }
  115. }
  116. int l = 0,r = 500,mid;
  117. while (l < r){
  118. mid = l + r >> 1;
  119. if (check(mid)) r = mid;
  120. else l = mid + 1;
  121. }
  122. printf("%d\n",l);
  123. return 0;
  124. }

BZOJ1189 [HNOI2007]紧急疏散evacuate 【二分 + 网络流】的更多相关文章

  1. bzoj 1189 [HNOI2007]紧急疏散evacuate 二分+网络流

    [HNOI2007]紧急疏散evacuate Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 3626  Solved: 1059[Submit][St ...

  2. BZOJ1189: [HNOI2007]紧急疏散evacuate 二分+最大流

    1189: [HNOI2007]紧急疏散evacuate Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1132  Solved: 412[Submi ...

  3. BZOJ1189: [HNOI2007]紧急疏散evacuate(二分答案,最大流)

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

  4. Bzoj1189 [HNOI2007]紧急疏散evacuate

    1189: [HNOI2007]紧急疏散evacuate Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2293  Solved: 715 Descr ...

  5. bzoj千题计划132:bzoj1189: [HNOI2007]紧急疏散evacuate

    http://www.lydsy.com/JudgeOnline/problem.php?id=1189 二分答案 源点向人连边,流量为1 门拆为mid个点,同一个门的第j个点向第j+1个点连边,流量 ...

  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(最大流,枚举)

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

  8. 【BZOJ1189】[HNOI2007]紧急疏散evacuate 动态加边网络流

    [BZOJ1189][HNOI2007]紧急疏散evacuate Description 发生了火警,所有人员需要紧急疏散!假设每个房间是一个N M的矩形区域.每个格子如果是'.',那么表示这是一块空 ...

  9. BZOJ 1189: [HNOI2007]紧急疏散evacuate( BFS + 二分答案 + 匈牙利 )

    我们可以BFS出每个出口到每个人的最短距离, 然后二分答案, 假设当前答案为m, 把一个出口拆成m个表示m个时间, 点u到出口v的距离为d, 那么u->v的[d, m]所有点连边, 然后跑匈牙利 ...

随机推荐

  1. Java 设计模式之中介者模式

    本文继续23种设计模式系列之中介者模式.   定义 用一个中介者对象封装一系列的对象交互,中介者使各对象不需要显示地相互作用,从而使耦合松散,而且可以独立地改变它们之间的交互.   角色 抽象中介者: ...

  2. React 官方脚手架 create-react-app快速生成新项目

    进入新公司已经半年了,各个业务线,技术栈都已经熟悉,工作也已经游刃有余,决定慢下脚步,沉淀积累,回顾一下所用技术栈所包含的基本知识,以及再公司中的实战. 首先回顾新项目搭建 react脚手架目前使用较 ...

  3. python_105_类的特殊成员方法

    aa.py class C(): def __init__(self): self.name='QiZhiguang' 类的特殊成员方法: # 1. __doc__ 表示类的描述信息 class Do ...

  4. java基础—super关键字

    一.super关键字

  5. ovs的学习

    本来编辑好了的, 结果忘了保存, 坑爹,直接把人家的网址贴上来吧 http://blog.chinaunix.net/uid-20737871-id-4333314.html 昨天遇到一个问题(虚拟机 ...

  6. FMDB中的数据处理

    [self.db executeUpdate:@"create table test (a text, b text, c integer, d double, e double)" ...

  7. Git基本操作笔记:初始化,用户设置,撤销修改

    1. Git 初始化 git init git  remote add repos_name repos_url git add . git commit -m 'commit message' gi ...

  8. Python基础——时间

    导入时间模块 import time 时间戳 print(time.time()) 获取本地时间 print(time.localtime(time.time())) 时间显示格式化 print(ti ...

  9. SpringMVC总结以及在面试中的一些问题.

    1.简单的谈一下SpringMVC的工作流程? 流程 1.用户发送请求至前端控制器DispatcherServlet 2.DispatcherServlet收到请求调用HandlerMapping处理 ...

  10. GPIO程序在PC上的模拟学习

    #include <stdio.h> #include <malloc.h> #include <memory.h> typedef struct gpio { i ...