二分答案+判定,对于一个答案,源点向每一个点连一条流量为1的边,每一扇门向汇点连一条流量为时间的边,每一个人向每一个在答案时间内能走到的门连一条流量为1的边,跑最大流并判断流量是否等于人数。

然而自从bzoj新增数据后就跑不过了,原因是不能保证有一组最优撤离方案使得在最后一个时刻以前(最后一个时刻可能人不够),每一扇门每一个时刻都有人出去(具体数据见bzoj讨论板)。

可以对门拆为时间个点,每一个点向它到某扇门的最早时间以后每一个时刻的门连一条流量为1的边,每一个门现在只有1的流量,再跑网络流即可(只要开40000个点和5000000条边即可,当然最坏的点数/边数要比这个大)。

  1 #include<bits/stdc++.h>
2 using namespace std;
3 #define N 50005
4 #define id i*m+j+1
5 struct ji{
6 int nex,to,len;
7 }edge[N*100];
8 queue<int>q;
9 int E,T,n,m,pe,head[N],work[N],d[N],vis[405][405],bh[405][41];
10 char s[31][31];
11 void add(int x,int y,int z){
12 edge[E].nex=head[x];
13 edge[E].to=y;
14 edge[E].len=z;
15 head[x]=E++;
16 if (E&1)add(y,x,0);
17 }
18 bool bfs(int k){
19 memset(d,-1,sizeof(d));
20 q.push(k);
21 d[k]=0;
22 while (!q.empty()){
23 k=q.front();
24 q.pop();
25 for(int i=head[k];i!=-1;i=edge[i].nex)
26 if ((edge[i].len)&&(d[edge[i].to]<0)){
27 d[edge[i].to]=d[k]+1;
28 q.push(edge[i].to);
29 }
30 }
31 return d[T]>=0;
32 }
33 int dfs(int k,int s){
34 if (k==T)return s;
35 for(int &i=work[k];i!=-1;i=edge[i].nex)
36 if ((edge[i].len)&&(d[edge[i].to]==d[k]+1)){
37 int p=dfs(edge[i].to,min(s,edge[i].len));
38 if (p){
39 edge[i].len-=p;
40 edge[i^1].len+=p;
41 return p;
42 }
43 }
44 return 0;
45 }
46 int dinic(){
47 int k,ans=0;
48 while (bfs(0)){
49 memcpy(work,head,sizeof(head));
50 while (k=dfs(0,0x3f3f3f3f))ans+=k;
51 }
52 return ans;
53 }
54 bool pd(int mid){
55 memset(head,-1,sizeof(head));
56 E=0;
57 for(int i=0;i<n;i++)
58 for(int j=0;j<m;j++){
59 if (s[i][j]=='.'){
60 add(0,id,1);
61 for(int k=0;k<n*m;k++)
62 if (s[k/m][k%m]=='D')
63 for(int l=vis[id][k];l<=mid;l++)add(id,bh[k+1][l],1);
64 }
65 if (s[i][j]=='D')
66 for(int k=1;k<=mid;k++)add(bh[id][k],T,1);
67 }
68 return dinic()==pe;
69 }
70 int main(){
71 scanf("%d%d",&n,&m);
72 memset(head,-1,sizeof(head));
73 for(int i=0;i<n;i++)scanf("%s",s[i]);
74 for(int i=0;i<n;i++)
75 for(int j=0;j<m;j++)
76 if (s[i][j]!='X'){
77 if ((j)&&(s[i][j-1]!='X')&&((s[i][j-1]!='D')||(s[i][j]!='D')))add(id,id-1,1);
78 if ((j<m-1)&&(s[i][j+1]!='X')&&((s[i][j+1]!='D')||(s[i][j]!='D')))add(id,id+1,1);
79 if ((i)&&(s[i-1][j]!='X')&&((s[i-1][j]!='D')||(s[i][j]!='D')))add(id,id-m,1);
80 if ((i<n-1)&&(s[i+1][j]!='X')&&((s[i+1][j]!='D')||(s[i][j]!='D')))add(id,id+m,1);
81 }
82 for(int i=0;i<n;i++)
83 for(int j=0;j<m;j++)
84 if (s[i][j]=='.'){
85 bfs(id);
86 pe++;
87 for(int k=1;k<=n*m;k++)
88 if (d[k]==-1)vis[id][k-1]=10000;
89 else vis[id][k-1]=d[k];
90 }
91 T=n*m+1;
92 for(int i=0;i<n;i++)
93 for(int j=0;j<m;j++)
94 if (s[i][j]=='D')
95 for(int k=1;k<=pe;k++)bh[id][k]=T++;
96 int l=0,r=pe+1;
97 while (l<r){
98 int mid=(l+r>>1);
99 if (pd(mid))r=mid;
100 else l=mid+1;
101 }
102 if (l>pe)printf("impossible");
103 else printf("%d",l);
104 }

[bzoj1189]紧急疏散的更多相关文章

  1. BZOJ-1189 紧急疏散evacuate BFS预处理+最大流+二分判定+神建模!!

    绝世污题,垃圾题,浪费我一整天青春! 1189: [HNOI2007]紧急疏散evacuate Time Limit: 10 Sec Memory Limit: 162 MB Submit: 1262 ...

  2. 【BZOJ1189】紧急疏散(二分答案,最大流)

    [BZOJ1189]紧急疏散(二分答案,最大流) 题面 Description 发生了火警,所有人员需要紧急疏散!假设每个房间是一个N M的矩形区域.每个格子如果是'.',那么表示这是一块空地:如果是 ...

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

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

  4. Bzoj1189 [HNOI2007]紧急疏散evacuate

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

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

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

  6. BZOJ1189:[HNOI2007]紧急疏散EVACUATE(最大流,枚举)

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

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

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

  8. bzoj1189 [HNOI2007]紧急疏散

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

  9. 【bzoj1189】[HNOI2007]紧急疏散evacuate BFS最短路+动态加边网络流

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

随机推荐

  1. Kubernetes client-go 源码分析 - Reflector

    概述入口 - Reflector.Run()核心 - Reflector.ListAndWatch()Reflector.watchHandler()NewReflector()小结 概述 源码版本: ...

  2. tcl概述

    tcl,全名tool command language,是一种通用的工具语言. 1)每个命令之间,通过换行符或者分号隔开: 2)tcl的每个命令包含一个或者多个单词,默认第一个单词表示命令,第二个单词 ...

  3. 分布式事物SAGA

    目录 概述SAGA SAGA的执行方式 存在的问题 重试机制 SAGA VS TCC 实现SAGA的框架 概述SAGA SAGA是1987 Hector & Kenneth 发表的论文,主要是 ...

  4. Unity——计时器功能实现

    Unity计时器 Demo展示 介绍 游戏中有非常多的计时功能,比如:各种cd,以及需要延时调用的方法: 一般实现有一下几种方式: 1.手动计时 float persistTime = 10f flo ...

  5. kviy TextInput 触发事件

    from kivy.uix.widget import Widget from kivy.app import App from kivy.lang import Builder Builder.lo ...

  6. [技术博客]WEB实现划词右键操作

    [技术博客]WEB实现划词右键操作 一.功能解释 简单地对题目中描述的功能进行解释:在浏览器中,通过拖动鼠标选中一个词(或一段文字),右键弹出菜单,且菜单为自定义菜单,而非浏览器本身的菜单.类似的功能 ...

  7. Noip模拟49 2021.9.7

    T1 reverse 又一道板子打假的挂分题,直接挂到倒二.. 考场上思路神奇,居然想到用$bfs$建边然后跑最短路, 其实当时也想到了直接$bfs$,但是不知道为啥觉得$dij$屌就没直接打$bfs ...

  8. Noip模拟17 2021.7.16

    我愿称这场考试为STL专练 T1 世界线 巧妙使用$bitset$当作vis数组使用,内存不会炸,操作还方便,的确是极好的. 但是这个题如果不开一半的$bitset$是会炸内存的,因为他能开得很大,但 ...

  9. [LGP2758]编辑距离

    目录 题目 题目描述 输入格式 输出格式 输入输出样例 题目分析 状态转移方程 初始状态 结束状态 Code 题目 题目描述 设A和B是两个字符串.我们要用最少的字符操作次数,将字符串A转换为字符串B ...

  10. C++实现红黑树

    红黑树的应用: 利用key_value对,快速查找,O(logn) socket与客户端id之间,形成映射关系(socket, id) 内存分配管理 一整块内存,不断分配小块 每分配一次,就加入到红黑 ...