P3191 [HNOI2007]紧急疏散EVACUATE
这一题很容易想到网络流
一开始傻逼地模拟整个图每一个时间的情况,显然会爆炸
发现我们只要考虑起点到门之间的距离,不用每一步只走一格
所以直接 $BFS$ 预处理距离然后二分答案,网络流判断即可
注意到了门就不能走了,所以门不能连边出去
总的来说挺傻逼的一题...但是我就是没想到...
某位不愿意透露姓名的神仙还有一种牛逼的费用流做法,代码极短$STO$
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
using namespace std;
typedef long long ll;
inline int read()
{
int x=,f=; char ch=getchar();
while(ch<''||ch>'') { if(ch=='-') f=-; ch=getchar(); }
while(ch>=''&&ch<='') { x=(x<<)+(x<<)+(ch^); ch=getchar(); }
return x*f;
}
const int N=2e5+,M=5e6+,INF=1e9+,xx[]={,,,-},yy[]={,,-,};
int fir[N],from[M<<],to[M<<],val[M<<],cntt=;
inline void add(int a,int b,int c)
{
from[++cntt]=fir[a]; fir[a]=cntt;
to[cntt]=b; val[cntt]=c;
from[++cntt]=fir[b]; fir[b]=cntt;
to[cntt]=a; val[cntt]=;
}
int n,m,tot,id[][][],sum;
int dep[N],S,T;
queue <int> Q;
bool BFS()
{
for(int i=;i<=tot;i++) dep[i]=;
Q.push(S); dep[S]=;
while(!Q.empty())
{
int x=Q.front(); Q.pop();
for(int i=fir[x];i;i=from[i])
{
int &v=to[i]; if(dep[v]||(!val[i])) continue;
dep[v]=dep[x]+; Q.push(v);
}
}
return dep[T]>;
}
int DFS(int x,int mxfl)
{
if(x==T||!mxfl) return mxfl;
int fl=,res;
for(int i=fir[x];i;i=from[i])
{
int &v=to[i]; if(dep[v]!=dep[x]+||!val[i]) continue;
if( res=DFS(v,min(mxfl,val[i])) )
{
mxfl-=res; fl+=res;
val[i]-=res; val[i^]+=res;
if(!mxfl) break;
}
}
return fl;
}
char mp[][];
int dis[][][][];
struct dat{
int x,y;
dat (int a=,int b=) { x=a,y=b; }
};
queue <dat> q;
void pre()
{
memset(dis,0x3f,sizeof(dis));
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
{
if(mp[i][j]!='.') continue;
q.push(dat(i,j)); dis[i][j][i][j]=;
while(!q.empty())
{
dat u=q.front(); q.pop();
for(int k=;k<;k++)
{
int tx=u.x+xx[k],ty=u.y+yy[k];
if(tx<||tx>n||ty<||ty>m||mp[tx][ty]=='X'||dis[i][j][tx][ty]<M) continue;
dis[i][j][tx][ty]=dis[i][j][u.x][u.y]+;
if(mp[tx][ty]!='D') q.push(dat(tx,ty));
}
}
}
}
bool check(int mid)
{
for(int i=;i<=tot;i++) fir[i]=; tot=; S=,T=; cntt=;
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
if(mp[i][j]=='.') id[][i][j]=++tot,add(S,tot,);
for(int t=;t<=mid;t++)
for(int k=;k<=n;k++)
for(int l=;l<=m;l++)
if(mp[k][l]=='D') id[t][k][l]=++tot,add(tot,T,);
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
{
if(mp[i][j]!='.') continue;
for(int t=;t<=mid;t++)
for(int k=;k<=n;k++)
for(int l=;l<=m;l++)
if(mp[k][l]=='D'&&dis[i][j][k][l]<=t) add(id[][i][j],id[t][k][l],INF);
}
int now=;
while(BFS())
{
now+=DFS(S,INF);
if(now>=sum) break;
}
for(int t=;t<=mid;t++)
for(int i=;i<=n;i++)
for(int j=;j<=m;j++) id[t][i][j]=;
return now>=sum;
}
int main()
{
n=read(),m=read();
for(int i=;i<=n;i++) scanf("%s",mp[i]+);
for(int i=;i<=n;i++)
for(int j=;j<=m;j++) sum+=(mp[i][j]=='.');
pre();
int L=,R=n*m,mid,ans=M;
while(L<=R)
{
mid=L+R>>;
if(check(mid)) R=mid-,ans=mid;
else L=mid+;
}
if(ans==M) printf("impossible\n");
else printf("%d\n",ans);
return ;
}
P3191 [HNOI2007]紧急疏散EVACUATE的更多相关文章
- P3191 [HNOI2007]紧急疏散EVACUATE(费用流)
P3191 [HNOI2007]紧急疏散EVACUATE 费用流+卡常优化 我们只关心一个人通过门时的时间,在空地的行走时间可以分层维护 于是根据时间分层,到门的时候再计算代价,即代价$=$层数 每经 ...
- luogu P3191 [HNOI2007]紧急疏散EVACUATE
传送门 qwq这题好大力 首先可以预处理出每个人到每个门前面那个格子的最早时间,然后答案如果比最小答案大的话也是合法的,所以可以二分最终答案.检查\(mid\)是否合法就考虑每个人要去哪个门才会合法, ...
- 洛谷 P3191 [HNOI2007]紧急疏散EVACUATE(网络最大流)
题解 二分答案+Dinic最大流 二分答案\(mid\) 把门拆成\(mid\)个时间点的门 相邻时间的门连一条\(inf\)的边 预处理出每个门到每个人的最短时间 为\(dis[k][i][j]\) ...
- 题解 P3191 [HNOI2007]紧急疏散EVACUATE
题解 本篇题解做法为BFS+二分+最大流 二分需要撤离的时间,也就是答案(这算是一个比较套路的了) 重点在于建模(设时间为 \(tim\)): 我们将每个门拆点,拆成 \(tim\) 个,每个点向汇点 ...
- Bzoj1189 [HNOI2007]紧急疏散evacuate
1189: [HNOI2007]紧急疏散evacuate Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 2293 Solved: 715 Descr ...
- BZOJ1189: [HNOI2007]紧急疏散evacuate 二分+最大流
1189: [HNOI2007]紧急疏散evacuate Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1132 Solved: 412[Submi ...
- BZOJ 1189: [HNOI2007]紧急疏散evacuate( BFS + 二分答案 + 匈牙利 )
我们可以BFS出每个出口到每个人的最短距离, 然后二分答案, 假设当前答案为m, 把一个出口拆成m个表示m个时间, 点u到出口v的距离为d, 那么u->v的[d, m]所有点连边, 然后跑匈牙利 ...
- [HNOI2007]紧急疏散EVACUATE (湖南2007年省选)
[HNOI2007]紧急疏散EVACUATE 题目描述 发生了火警,所有人员需要紧急疏散!假设每个房间是一个N M的矩形区域.每个格子如果是'.',那么表示这是一块空地:如果是'X',那么表示这是一面 ...
- bzoj千题计划132:bzoj1189: [HNOI2007]紧急疏散evacuate
http://www.lydsy.com/JudgeOnline/problem.php?id=1189 二分答案 源点向人连边,流量为1 门拆为mid个点,同一个门的第j个点向第j+1个点连边,流量 ...
随机推荐
- LeetCode--009--回文数(python)
判断一个数是否为回文数,回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数. 通常让数字逆序,然后判断和原数字是否相等,这里只需逆序一般就可以. case1.奇数位例如判断12321 whi ...
- webkit内核的浏览器常见7种分别是..
Google Chrome Safari 遨游浏览器 3.x 搜狗浏览器 阿里云浏览器 QQ浏览器 360浏览器 ...
- Java——容器(Set)
[Set接口] <1>Set接口是Collection的子接口,Set接口没有提供额外的方法. <2>实现Set接口的容器类中的元素是没有顺序的,而且不可以重复. <3& ...
- [BZOJ3236]:[Ahoi2013]作业(莫队+分块)
题目传送门 题目描述 此时已是凌晨两点,刚刚做了$Codeforces$的小$A$掏出了英语试卷.英语作业其实不算多,一个小时刚好可以做完.然后是一个小时可与做完的数学作业,接下来是分别都是一个小时可 ...
- CruiseControl.NET配置
CruiseControl.NET简介 CruiseControl.NET是.net平台下,一个开源的自动化持续集成工具. 它是一个程序套件,但其核心是一个叫做CruiseControl.NET Se ...
- Mac sublime安装package controller
https://packagecontrol.io/installation#st2 链接被墙了这个. 我拿来放在这里. The simplest method of installation is ...
- Mysql数据库密码忘记的解决办法
密码忘记——破解密码 跳过授权方式,直接登录!! 1.以管理员身份打开cmd 2.停掉mysql服务端 C:\WINDOWS\system32>net stop mysql MySQL 服务正在 ...
- 架构-层-DAL:DAL
ylbtech-架构-层-DAL:DAL DAL是数据访问层的英文缩写,即为数据访问层(Data Access Layer).其功能主要是负责数据库的访问.简单地说就是实现对数据表的Select(查询 ...
- 【SVN】 一次SVN 修复笔记
同事乱提交了一个版本之后,SVN上最新版本出现了问题. 原本按照网上其他人的说法,可以手动到服务器端干掉最新版的存档,并修改版本记录到前一个版本号即可,但是这应该是个坑. 掉进这个坑后,需要解决,又不 ...
- 阶段1 语言基础+高级_1-3-Java语言高级_06-File类与IO流_04 IO字节流_4_字节输出流写入数据到文件
数据由内存写入到硬盘中 构造函数传的路径是一个相对路径.有异常需要捕获异常 释放资源 这三个方法,都有异常 IO异常是父类,所以这里只需要抛出IO异常就可以了. 运行程序.目录内多了个a.txt文件 ...