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

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

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

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

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

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

  3. bzoj1189 [HNOI2007]紧急疏散EVACUATE spfa+网络流+二分

    这个题是非常暴力的匹配问题. 首先最好想的思路是给每个人分门的决策, 每个人到每个门的距离直接暴力最短路即可 但不能算出一个门被多个人经过的情况 所以就有了暴力的想法,再给每个人.对每一个门分配一个时 ...

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

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

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

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

  6. poj2455 Secret Milking Machine(二分答案+最大流)

    二分答案,双向边网络流,反向边容量直接设为val即可.可以选择的边容量为1,跑最大流,看是否满流(是否存在K条路径). #include <cstdio> #include <cst ...

  7. BZOJ2547 CTSC2002玩具兵(最短路径+二分答案+最大流)

    先不考虑只有一个显得有些特殊的天兵. 可以发现超能力的作用实质上是使兵更换职业.每一个兵到达某个位置最少需要更换职业的次数是彼此独立的,因为如果需要某两人互换职业可以使他们各自以当前职业到达需要到的地 ...

  8. bzoj 3993 星际战争 - 二分答案 - 最大流

    3333年,在银河系的某星球上,X军团和Y军团正在激烈地作战.在战斗的某一阶段,Y军团一共派遣了N个巨型机器人进攻X军团的阵地,其中第i个巨型机器人的装甲值为Ai.当一个巨型机器人的装甲值减少到0或者 ...

  9. BZOJ 3993 Luogu P3324 [SDOI2015]星际战争 (最大流、二分答案)

    字符串终于告一段落了! 题目链接: (bzoj) https://www.lydsy.com/JudgeOnline/problem.php?id=3993 (luogu) https://www.l ...

  10. BZOJ 1305 dance跳舞(最大流+二分答案)

    题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1305 解题思路: 转自:https://blog.csdn.net/u012288458 ...

最新文章

  1. Litmus代码质量平台实践总结
  2. 如何用飞书统计并跟进个税年度汇算清缴情况?
  3. 第 1 章 虚拟化 - 013 - 动手实践 Linux VLAN
  4. 电子计算机信息工程都是做什么的,电子信息工程专业将来干什么 就业前景好不好...
  5. 成年人的样子是什么样子_不只是看样子
  6. 互联网晚报 | 4月11日 星期一 | 苏州放宽住房限售;苹果确认开始在印度生产iPhone 13;民航局将上报民航专项检查方案...
  7. 2017.3.20-morning
  8. MySQL通过SQL语句生成实体类_使用sql生成表对应的CRUD语句和表对应java实体类的实例变量...
  9. mysql字符串多行字符串数组_MySQL从跨行任意长的字符串数组中获取不同的值
  10. PHP动态网页设计与制作案例教程pdf
  11. app客户端上传图片实现方式
  12. android打开系统文件怎么打开方式,Android调用系统应用打开任意文件
  13. 学计算机的怎么防辐射,一种学生用防辐射计算机的制作方法
  14. POJ 2774 Long Long Message
  15. 2021-09-03 Elasticsearch基操
  16. “.”和“->”的区别
  17. Intel PinTools使用笔记——INS_InsertCall()
  18. 查看浏览器兼容性的专门网站,收藏下哦
  19. winapi属于底层开发吗_请问一下关于VC++的Winmain函数(WINAPI是什么?)
  20. 父类指针转换成子类指针

热门文章

  1. 【JTAG、SBW、BSL】MSP430的BSL
  2. Autovue集成全过程
  3. F1DC2706蓝牙模块的射频特性及功耗测试
  4. 怎么彻底禁用Cortana小娜?
  5. css 多余省略号_css设置文字多余部分显示省略号
  6. 可能是最通俗的Lempel-Ziv-Welch (LZW)无损压缩算法详述
  7. 大话C语言——优化结构控制(一)
  8. 干货|浅谈iOS端短视频SDK技术实现
  9. centos 中 Discuz 论坛模板配置问题
  10. 一些情况及问题的说明