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

Description

发生了火警,所有人员需要紧急疏散!假设每个房间是一个N M的矩形区域。每个格子如果是'.',那么表示这是一
块空地;如果是'X',那么表示这是一面墙,如果是'D',那么表示这是一扇门,人们可以从这儿撤出房间。已知门
一定在房间的边界上,并且边界上不会有空地。最初,每块空地上都有一个人,在疏散的时候,每一秒钟每个人都
可以向上下左右四个方向移动一格,当然他也可以站着不动。疏散开始后,每块空地上就没有人数限制了(也就是
说每块空地可以同时站无数个人)。但是,由于门很窄,每一秒钟只能有一个人移动到门的位置,一旦移动到门的
位置,就表示他已经安全撤离了。现在的问题是:如果希望所有的人安全撤离,最短需要多少时间?或者告知根本
不可能。

Input

第一行是由空格隔开的一对正整数N与M,3<=N <=20,3<=M<=20,
以下N行M列描述一个N M的矩阵。其中的元素可为字符'.'、'X'和'D',且字符间无空格。

Output

只有一个整数K,表示让所有人安全撤离的最短时间,
如果不可能撤离,那么输出'impossible'(不包括引号)。

Sample Input

5 5
XXXXX
X...D
XX.XX
X..XX
XXDXX

Sample Output

3
解题思路:
考虑每个点到每个门的最短路一定所以先Bfs/Dijstra一遍得到每个点到每个门到最短距离。
考虑随着时间的推移,每个点能够到达的门也就越多,所以可以说是动态加边。
这时的正确方法是二分答案,建图网络流。
显然是源点连人,在时间允许的情况下人连门,容量为1。门连汇点,容量为T。
这样做理论上是很好的,但是有一个问题,那就是本题的特殊性,每个格子可以重复走人但是门只能一个一个出。
这就十分不和谐了,因为上面的做法并不能处理两个人同时到达的情况。
考虑一个问题,到底是什么性质没有被体现导致建图瑕疵。
这里可以认为门在T时刻关闭,那么本质上每个人都有一个剩余时间,假如说一起到然后一个一个出,
这里的问题就是假如说一起到的人比较多,假如说大于T那么一定不能全部出去。
所以需要有一个条件来限制每个人到达时还剩多少时间,换句话说,需要表现他究竟是什么时间到达的。
这样,将每个门拆成T个点,代表该时刻到达的门(相当于给门分层)。
每个点向到达时间的门连边,每层门向下一层连流量为$inf$的边。
跑最大流验证就好了。
代码:
  1 #include<queue>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 const int oo=0x3f3f3f3f;
  6 struct int_2{int TIME;int NO;};
  7 struct pnt{
  8     int hd;
  9     int lyr;
 10     int now;
 11 }p[1000000];
 12 struct ent{
 13     int twd;
 14     int vls;
 15     int lst;
 16     int his;
 17 }e[5000000];
 18 struct OVO{
 19     int_2 pro;
 20     int i;
 21     int j;
 22 };
 23 int cnt;
 24 int n,m;
 25 int s,t;
 26 int pnum;
 27 char tmp[100];
 28 int no[21][21];
 29 int mp[21][21];
 30 bool vis[21][21];
 31 bool hvv[21][21];
 32 std::queue<int>Q;
 33 std::queue<OVO>P;
 34 std::vector<int>T[1000];
 35 std::vector<int_2>dr[21][21];
 36 void ade(int f,int t,int v)
 37 {
 38     cnt++;
 39     e[cnt].twd=t;
 40     e[cnt].vls=v;
 41     e[cnt].his=v;
 42     e[cnt].lst=p[f].hd;
 43     p[f].hd=cnt;
 44     return ;
 45 }
 46 bool bfs(void)
 47 {
 48     for(int i=1;i<=n;i++)
 49     {
 50         for(int j=1;j<=m;j++)
 51         {
 52             if(mp[i][j]==2)
 53             {
 54                 while(!P.empty())
 55                     P.pop();
 56                 P.push((OVO){(int_2){0,no[i][j]},i,j});
 57                 while(!P.empty())
 58                 {
 59                     OVO x=P.front();
 60                     P.pop();
 61                     int ii=x.i;
 62                     int jj=x.j;
 63                     if(vis[ii][jj])
 64                         continue;
 65                     vis[ii][jj]=true;
 66                     if(mp[ii][jj]==1)
 67                         dr[ii][jj].push_back(x.pro);
 68                     x.pro.TIME++;
 69                     OVO y;
 70                     y=x;
 71                     y.i++;
 72                     if(y.i<=n)
 73                     {
 74                         if(mp[y.i][y.j]==1)
 75                         {
 76                             P.push(y);
 77                         }
 78                     }
 79                     y=x;
 80                     y.i--;
 81                     if(y.i>0)
 82                     {
 83                         if(mp[y.i][y.j]==1)
 84                         {
 85                             P.push(y);
 86                         }
 87                     }
 88                     y=x;
 89                     y.j++;
 90                     if(y.j<=m)
 91                     {
 92                         if(mp[y.i][y.j]==1)
 93                         {
 94                             P.push(y);
 95                         }
 96                     }
 97                     y=x;
 98                     y.j--;
 99                     if(y.j>0)
100                     {
101                         if(mp[y.i][y.j]==1)
102                         {
103                             P.push(y);
104                         }
105                     }
106                 }
107                 for(int ii=1;ii<=n;ii++)
108                 {
109                     for(int jj=1;jj<=m;jj++)
110                     {
111                         if(vis[ii][jj])
112                             hvv[ii][jj]=true;
113                         vis[ii][jj]=false;
114                     }
115                 }
116             }
117         }
118     }
119     for(int i=1;i<=n;i++)
120     {
121         for(int j=1;j<=m;j++)
122         {
123             if(!hvv[i][j]&&mp[i][j]==1)
124                 return true;
125         }
126     }
127     return false;
128 }
129 bool Bfs(void)
130 {
131     while(!Q.empty())Q.pop();
132     for(int i=1;i<=t;i++)
133         p[i].lyr=0;
134     p[s].lyr=1;
135     Q.push(s);
136     while(!Q.empty())
137     {
138         int x=Q.front();
139         Q.pop();
140         for(int i=p[x].hd;i;i=e[i].lst)
141         {
142             int to=e[i].twd;
143             if(p[to].lyr==0&&e[i].vls>0)
144             {
145                 p[to].lyr=p[x].lyr+1;
146                 if(to==t)
147                     return true;
148                 Q.push(to);
149             }
150         }
151     }
152     return false;
153 }
154 int Dfs(int x,int fll)
155 {
156     if(x==t)
157         return fll;
158     for(int& i=p[x].now;i;i=e[i].lst)
159     {
160         int to=e[i].twd;
161         if(p[to].lyr==p[x].lyr+1&&e[i].vls>0)
162         {
163             int ans=Dfs(to,std::min(fll,e[i].vls));
164             if(ans>0)
165             {
166                 e[i].vls-=ans;
167                 e[((i-1)^1)+1].vls+=ans;
168                 return ans;
169             }
170         }
171     }
172     return 0;
173 }
174 int Dinic(void)
175 {
176     int ans=0;
177     while(Bfs())
178     {
179         for(int i=1;i<=t;i++)
180             p[i].now=p[i].hd;
181         int dlt;
182         while(dlt=Dfs(s,oo))
183             ans+=dlt;
184     }
185     return ans;
186 }
187 bool Check(int x)
188 {
189     for(int i=1;i<=t;i++)
190         p[i].hd=0;
191     cnt=0;
192     int lcnt=n*m;
193     for(int i=1;i<=n;i++)
194         for(int j=1;j<=m;j++)
195             if(mp[i][j]==2)
196             {
197                 T[no[i][j]].clear();
198                 for(int k=0;k<=x;k++)
199                     T[no[i][j]].push_back(++lcnt);
200             }
201     s=lcnt+1;
202     t=s+1;
203     for(int i=1;i<=n;i++)
204     {
205         for(int j=1;j<=m;j++)
206         {
207             if(mp[i][j]==1)
208             {
209                 ade(s,no[i][j],1);
210                 ade(no[i][j],s,0);
211                 for(int k=0;k<dr[i][j].size();k++)
212                 {
213                     if(dr[i][j][k].TIME<=x)
214                     {
215                         ade(no[i][j],T[dr[i][j][k].NO][dr[i][j][k].TIME],1);
216                         ade(T[dr[i][j][k].NO][dr[i][j][k].TIME],no[i][j],0);
217                     }
218                 }
219             }else if(mp[i][j]==2)
220             {
221                 for(int k=0;k<=x;k++)
222                 {
223                     ade(T[no[i][j]][k],t,1);
224                     ade(t,T[no[i][j]][k],0);
225                     if(k!=x)
226                     {
227                         ade(T[no[i][j]][k],T[no[i][j]][k+1],oo);
228                         ade(T[no[i][j]][k+1],T[no[i][j]][k],0);
229                     }
230                 }
231             }
232         }
233     }
234     return pnum==Dinic();
235 }
236 int main()
237 {
238 //    freopen("a.in","r",stdin);
239     scanf("%d%d",&n,&m);
240     for(int i=1;i<=n;i++)
241     {
242         scanf("%s",tmp+1);
243         for(int j=1;j<=m;j++)
244         {
245             no[i][j]=++cnt;
246             if(tmp[j]=='X')
247                 mp[i][j]=0;
248             if(tmp[j]=='.')
249                 mp[i][j]=1,
250                 pnum++;
251             if(tmp[j]=='D')
252                 mp[i][j]=2;
253         }
254     }
255     cnt=0;
256     if(bfs())
257     {
258         puts("impossible");
259         return 0;
260     }
261     int l=0,r=1000;
262     int ans;
263     while(l<=r)
264     {
265         int mid=(l+r)>>1;
266         if(Check(mid))
267         {
268             ans=mid;
269             r=mid-1;
270         }else
271             l=mid+1;
272     }
273     printf("%d\n",ans);
274     return 0;
275 }

 

转载于:https://www.cnblogs.com/blog-Dr-J/p/10238928.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/412452.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[vue]vue渲染模板时怎么保留模板中的HTML注释呢?

[vue]vue渲染模板时怎么保留模板中的HTML注释呢&#xff1f; <template comments>... </template>个人简介 我是歌谣&#xff0c;欢迎和大家一起交流前后端知识。放弃很容易&#xff0c; 但坚持一定很酷。欢迎大家一起讨论 主目录 与歌谣一起通关前端面试题

redis设置为null问题

查看源码后发现&#xff0c;redis没有删除方法&#xff0c;本想给他设置为null,但是redis报错&#xff0c;所有仔细想了一下&#xff0c;发现redis提供了一个时间限制方法&#xff0c;所有可以让redis的时间限制为1s&#xff0c;就想当于删除redis中的这个K。 转载于:https://w…

nacos 返回 403 unknown user 太他么坑了 源码解析

大家好&#xff0c;我是烤鸭&#xff1a; nacos 真的是有点意思&#xff0c;有时候哪怕某个jar包版本冲突了都可能导致莫名其妙的错误&#xff0c;源码走一波吧。 当前版本 <dependencies><dependency><groupId>org.springframework.boot</groupId>&…

[vue] Vue.observable你有了解过吗?说说看

[vue] Vue.observable你有了解过吗&#xff1f;说说看 让一个对象可响应。Vue 内部会用它来处理 data 函数返回的对象。返回的对象可以直接用于渲染函数和计算属性内&#xff0c;并且会在发生改变时触发相应的更新&#xff1b;也可以作为最小化的跨组件状态存储器。个人简介 …

[vue] 你知道style加scoped属性的用途和原理吗?

[vue] 你知道style加scoped属性的用途和原理吗&#xff1f; 在标签上绑定了自定义属性&#xff0c;防止css全局污染 但是很多时候使用ui框架如果加scope就不能覆盖&#xff0c;这个时候一般写sass 会在最外层包裹该组件名的id 就可以不使用scoped 了个人简介 我是歌谣&#x…

研发效能提升 maven依赖扫描 版本统一 漏洞版本提醒

大家好&#xff0c;我是烤鸭&#xff1a; 整点干货&#xff0c;代码级别的版本统一&#xff0c;以及漏洞版本的扫描。 背景 两个方面吧。 项目整体的架构不统一&#xff0c;springboot/cloud 配置/注册中心也用的不统一&#xff0c;版本更是五花八门&#xff0c;怎么快速的找…

[vue] 你期待vue3.0有什么功能或者改进的地方?

[vue] 你期待vue3.0有什么功能或者改进的地方&#xff1f; 用尤大的话说就是各种速度提升n倍。我希望在依赖node_modules能够做出调整&#xff0c;文件数目太多&#xff0c;开启项目每次都要下载个人简介 我是歌谣&#xff0c;欢迎和大家一起交流前后端知识。放弃很容易&…

Spring boot actuator端点启用和暴露

1.启用端点 默认情况下&#xff0c;除了shutdown端点是关闭的&#xff0c;其它的都是启用的。配置一个端点的启用&#xff0c;使用management.endpoint..enabled属性&#xff0c;下面的例子是启用shutdown端点&#xff1a; management.endpoint.shutdown.enabledtrue如果你个人…

java执行sql慢 navicat不慢 见鬼了

大家好&#xff0c;我是烤鸭&#xff1a; 有点意思的问题&#xff0c;代码提示接口超时(10s)&#xff0c;接口逻辑很简单&#xff0c;就一个sql查询。本来也想是sql慢&#xff0c;可是拿sql去Navicat执行下&#xff0c;一点不慢(50ms)。 环境 DB&#xff1a;SqlServer 连接池…

[vue] vue边界情况有哪些?

[vue] vue边界情况有哪些&#xff1f; 访问根实例、访问父组件、子组件个人简介 我是歌谣&#xff0c;欢迎和大家一起交流前后端知识。放弃很容易&#xff0c; 但坚持一定很酷。欢迎大家一起讨论 主目录 与歌谣一起通关前端面试题

函数的基础

函数的初识&#xff1a; 封装一个功能。 def 函数名(): 函数体 函数的返回值&#xff1a;return 1,结束函数。 2&#xff0c;返回给执行者&#xff08;函数名()&#xff09;值。 return ----> None return 单个值----> 单个值 return 多个值----> &#xff08;多…

windows docker mongodb

大家好&#xff0c;我是烤鸭&#xff1a; 今天翻博客&#xff0c;发现4年前的一篇草稿&#xff0c;抽空给完善下。原本草稿写的是linux下mongo使用&#xff0c;还有java的一些api&#xff0c;现在就用容器实现下。 容器部署 官方网站&#xff1a; https://www.mongodb.com/ w…

[vue] 如何在子组件中访问父组件的实例?

[vue] 如何在子组件中访问父组件的实例&#xff1f; this.$parent拿到父组件实例 this.$children拿到子组件实例&#xff08;数组&#xff09;个人简介 我是歌谣&#xff0c;欢迎和大家一起交流前后端知识。放弃很容易&#xff0c; 但坚持一定很酷。欢迎大家一起讨论 主目录…

[vue] watch的属性用箭头函数定义结果会怎么样?

[vue] watch的属性用箭头函数定义结果会怎么样&#xff1f; 因为箭头函数默绑定父级作用域的上下文&#xff0c;所以不会绑定vue实例&#xff0c;所以 this 是undefind个人简介 我是歌谣&#xff0c;欢迎和大家一起交流前后端知识。放弃很容易&#xff0c; 但坚持一定很酷。欢…

tensorflow的keras 与 原生keras几点比较

tensorflow的keras 与 原声keras几点比较&#xff0c;不是全面的比较&#xff0c;因为只是就使用时候发现的差异&#xff01; 使用函数式API时&#xff1a; 1. 定义模型模型时&#xff0c;用到输入的张量&#xff0c;也就是给Input的tensor赋值为你的inputs&#xff0c;在编译时…

[vue] 在vue项目中如何配置favicon?

[vue] 在vue项目中如何配置favicon&#xff1f; 也可以在当前项目部署的端口主目录下存放favicon.ico文件&#xff0c;默认就会显示该图标个人简介 我是歌谣&#xff0c;欢迎和大家一起交流前后端知识。放弃很容易&#xff0c; 但坚持一定很酷。欢迎大家一起讨论 主目录 与…

Is the byte array a result of corresponding serialization for DefaultDeserializer

大家好&#xff0c;我是烤鸭&#xff1a; 问题记录&#xff0c;上线之后懵逼的问题。只能回滚?每次都是上线来暴击&#xff0c;不然多查查文章也不至于这么被动。 报错日志 org.springframework.data.redis.serializer.SerializationException: Cannot deserialize; nes…

[vue] 你有使用过babel-polyfill模块吗?主要是用来做什么的?

[vue] 你有使用过babel-polyfill模块吗&#xff1f;主要是用来做什么的&#xff1f; Babel默认只转换新的JavaScript句法&#xff08;syntax&#xff09;&#xff0c;而不转换新的API&#xff0c;比如Iterator、Generator、Set、Maps、Proxy、Reflect、Symbol、Promise等全局对…

高级PHP工程师所应该具备的专业素养

高级PHP工程师所应该具备的专业素养 初次接触PHP&#xff0c;就为他的美所折服&#xff0c;于是一发不可收拾。 很多面试&#xff0c;很多人员能力要求都有“PHP高级工程师的字眼”&#xff0c;如果您真心喜欢PHP&#xff0c;并且您刚起步&#xff0c;那么我简单说说一个PHP高级…