bzoj 1189: [HNOI2007]紧急疏散evacuate 分层图最大流_拆点_二分
Description
Input
题解:
一眼分层图最短路,按时间将每个点拆开.
然而,空间时爆炸的,节点层数过多.
不过,我们有一个非常好的性质:由于任意时刻每个空格上不限人数,人们可以直接走最短路径走向每扇门.
这样,就不必对每一个空地拆点,只需将门按照时间拆开并连边即可.
处理最短路径我们选择 Floyd.
Code:
#include<bits/stdc++.h>
#define setIO(s) freopen(s".in","r",stdin)
#define maxn 100000
#define inf 100000
using namespace std;
namespace Dinic{
struct Edge{
int from,to,cap;
Edge(int a=0,int b=0,int c=0):from(a),to(b),cap(c){}
};
queue<int>Q;
vector<Edge>edges;
vector<int>G[maxn];
void add(int u,int v,int c){
edges.push_back(Edge(u,v,c));
edges.push_back(Edge(v,u,0));
int m=edges.size();
G[u].push_back(m-2);
G[v].push_back(m-1);
}
int S,T,vis[maxn],d[maxn],current[maxn];
int BFS(){
memset(vis,0,sizeof(vis));
vis[S]=1,d[S]=0; Q.push(S);
while(!Q.empty()){
int u=Q.front();Q.pop();
for(int sz=G[u].size(),i=0;i<sz;++i){
Edge r = edges[G[u][i]];
if(!vis[r.to] && r.cap>0) {
vis[r.to]=1,d[r.to]=d[u]+1;
Q.push(r.to);
}
}
}
return vis[T];
}
int dfs(int x,int cur){
if(x==T) return cur;
int flow=0,f;
for(int sz=G[x].size(),i=current[x];i<sz;++i){
current[x]=i;
Edge r = edges[G[x][i]];
if(d[r.to]==d[x]+1&&r.cap>0) {
if(f=dfs(r.to,min(cur,r.cap))) {
flow+=f,cur-=f;
edges[G[x][i]].cap-=f,edges[G[x][i]^1].cap+=f;
}
}
if(cur==0) break;
}
return flow;
}
int maxflow(){
int flow=0;
while(BFS()){
memset(current,0,sizeof(current));
flow+=dfs(S,inf);
}
return flow;
}
void re(){
S=T=0;
for(int i=0;i<maxn;++i) G[i].clear();
edges.clear();
}
};
char str[500];
int gr[500][500],d[500][500],ck[500][500];
#define idx(i,j) ((i-1)*m+j)
#define nex (id+10)
vector<int>gate,G[maxn];
int mapp[500][300],n,m,sum;
bool check(int t){
int id=0;
Dinic::re();
Dinic::S=0,Dinic::T=5000;
for(int sz=gate.size(),i=0;i<sz;++i) {
mapp[gate[i]][0]=++id; Dinic::add(id,5000,1);
for(int j=1;j<=t;++j) { mapp[gate[i]][j]=++id; Dinic::add(id-1,id,inf),Dinic::add(id,5000,1); }
}
int tot=n*m;
for(int i=1;i<=tot;++i) {
for(int sz=G[i].size(),j=0;j<sz;++j) if(d[i][G[i][j]]<=t) Dinic::add(i+nex,mapp[G[i][j]][d[i][G[i][j]]],1);
if(G[i].size()) Dinic::add(0,i+nex,1);
}
return (Dinic::maxflow()==sum);
}
int main(){
//setIO("input");
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i){
scanf("%s",str+1);
for(int j=1;j<=m;++j) {
if(str[j]=='.') gr[i][j]=0,++sum;
if(str[j]=='X') gr[i][j]=1;
if(str[j]=='D') { gr[i][j]=2; gate.push_back(idx(i,j)); }
}
}
for(int i=1;i<=n*m;++i)
for(int j=1;j<=n*m;++j) d[i][j]=inf;
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j) {
if(i-1>=1&&gr[i-1][j]!=1) d[idx(i,j)][idx(i-1,j)]=ck[idx(i,j)][idx(i-1,j)]=1;
if(i+1<=n&&gr[i+1][j]!=1) d[idx(i,j)][idx(i+1,j)]=ck[idx(i,j)][idx(i+1,j)]=1;
if(j+1<=m&&gr[i][j+1]!=1) d[idx(i,j)][idx(i,j+1)]=ck[idx(i,j)][idx(i,j+1)]=1;
if(j-1>=1&&gr[i][j-1]!=1) d[idx(i,j)][idx(i,j-1)]=ck[idx(i,j)][idx(i,j-1)]=1;
}
int tot=n*m;
for(int i=1;i<=tot;++i) ck[i][i]=1,d[i][i]=0;
for(int k=1;k<=tot;++k)
for(int i=1;i<=tot;++i)
for(int j=1;j<=tot;++j) if(ck[i][k]&&ck[k][j]) ck[i][j]=1;
for(int k=1;k<=tot;++k)
for(int i=1;i<=tot;++i)
for(int j=1;j<=tot;++j) if(ck[i][j]) d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j)
if(gr[i][j]==0){
bool flag=0;
for(int sz=gate.size(),t=0;t<sz;++t){
if(ck[idx(i,j)][gate[t]]) G[idx(i,j)].push_back(gate[t]);
flag=1;
}
if(!flag) { printf("impossible"); return 0; }
}
int l=1,r=400,ans,mid;
while(l<=r){
mid=(l+r)>>1;
if(check(mid)) ans=mid,r=mid-1;
else l=mid+1;
}
printf("%d",ans);
return 0;
}
bzoj 1189: [HNOI2007]紧急疏散evacuate 分层图最大流_拆点_二分的更多相关文章
- BZOJ 1189: [HNOI2007]紧急疏散evacuate( BFS + 二分答案 + 匈牙利 )
我们可以BFS出每个出口到每个人的最短距离, 然后二分答案, 假设当前答案为m, 把一个出口拆成m个表示m个时间, 点u到出口v的距离为d, 那么u->v的[d, m]所有点连边, 然后跑匈牙利 ...
- bzoj 1189 [HNOI2007]紧急疏散evacuate 二分+网络流
[HNOI2007]紧急疏散evacuate Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 3626 Solved: 1059[Submit][St ...
- BZOJ 1189 [HNOI2007]紧急疏散evacuate
Description 发生了火警,所有人员需要紧急疏散!假设每个房间是一个N M的矩形区域.每个格子如果是'.',那么表示这是一块空地:如果是'X',那么表示这是一面墙,如果是'D',那么表示这是一 ...
- 【BZOJ】1189: [HNOI2007]紧急疏散evacuate(二分+bfs+网络流)
http://www.lydsy.com/JudgeOnline/problem.php?id=1189 表示完全不会QAQ.... 于是膜拜题解orz 二分时间........... 于是转换成判定 ...
- 1189: [HNOI2007]紧急疏散evacuate - BZOJ
Description 发生了火警,所有人员需要紧急疏散!假设每个房间是一个N M的矩形区域.每个格子如果是'.',那么表示这是一块空地:如果是'X',那么表示这是一面墙,如果是'D',那么表示这是一 ...
- 1189: [HNOI2007]紧急疏散evacuate
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 3831 Solved: 1119[Submit][Status][Discuss] Descript ...
- 洛谷 P3191 [HNOI2007]紧急疏散EVACUATE(网络最大流)
题解 二分答案+Dinic最大流 二分答案\(mid\) 把门拆成\(mid\)个时间点的门 相邻时间的门连一条\(inf\)的边 预处理出每个门到每个人的最短时间 为\(dis[k][i][j]\) ...
- bzoj千题计划132:bzoj1189: [HNOI2007]紧急疏散evacuate
http://www.lydsy.com/JudgeOnline/problem.php?id=1189 二分答案 源点向人连边,流量为1 门拆为mid个点,同一个门的第j个点向第j+1个点连边,流量 ...
- Bzoj1189 [HNOI2007]紧急疏散evacuate
1189: [HNOI2007]紧急疏散evacuate Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 2293 Solved: 715 Descr ...
随机推荐
- delphi窗口的create和free,一个古老的话题
窗体分为模式窗体和无模式窗体. 模式窗体在创建窗口创建和释放: begin if not Assigned(FB_Input_JianYanDan) then FB_Input_JianYanDan ...
- 对Django框架中Cookie的简单理解
概念的理解:首先Cookie和Session一样,是django中用于视图保持状态的方案之一.为什么要进行视图保留呢,这是因为浏览器在向服务器发出请求时,服务器不会像人一样,有记忆,服务器像鱼一样,在 ...
- cogs 10. 信号无错传输
10. 信号无错传输 ★★☆ 输入文件:dlj.in 输出文件:dlj.out 简单对比时间限制:1 s 内存限制:128 MB [问题描述] 为提高传递信息的保密性和可靠性,两个军事 ...
- RubyMine快捷键
RubyMine快捷键 ctrl+shift+up/down 向上/向下移动代码段 alt+shift+up/down 向上/向下移动代码行 ctrl+y 删除一行 ctrl+shift+f10 运行 ...
- 如何在Eclipse引入JUnit测试
1.在Eclipse中引入JUnitjar文件 2.右键Build Path>Configure Bulid Path 3.Libraries>Add Library 4.Junit> ...
- MySQL出现Ignoring query to other database的问题
今天使用mysql的时候,输入随意一条命令都会出: Ignoring query to other database 这条错误信息,非常是奇怪. 后来才发现是登录数据库时.少了个-u的參数.. 正确的 ...
- sql server drop login failed
https://stackoverflow.com/questions/37275/sql-query-for-logins https://www.mssqltips.com/sqlserverti ...
- navicat数据库同步
10.168.95.246
- 关于类和对象的进一步讨论 C++
如果一个类中所有成员函数都是公用的,则可以在定义对象时对数据成员进行初始化: class Time { public: hour; minute; sec; }; Time t1={14,15,23 ...
- Linux Shell Scripting Cookbook 读书笔记 7
ping, du, ps, kill, 收集系统信息 判断网络中哪些主机是活动主机 #!/bin/bash for ip in 10.215.70.{1..255}; do ( ping $ip -c ...