BZOJ 1189: [HNOI2007]紧急疏散evacuate|网络流|二分答案
Posted ws_yzy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ 1189: [HNOI2007]紧急疏散evacuate|网络流|二分答案相关的知识,希望对你有一定的参考价值。
S连“。”流量为1
二分答案 x
算出每一个门到每一个点的距离若小于x连边 流量为1
门连T 流量为 x
其实这个题完全不用拆点
因为门限制的流量为x
若有x个点和门的dis<x
每个点到门的距离肯定<=x
而且dis=x的点最多有一个
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<iostream>
#include<algorithm>
#define T 99999
using namespace std;
int dx[]=0,0,-1,1;
int dy[]=-1,1,0,0;
int t[T];
int head[444],nxt[T],lst[T],v[T];
int id[33][33],mx[444],my[444];
int dis[33][33],q[T][2],S,W,h[T];
char s[33][33];int D[444];
int n,m,tot=1,cnt,top,pl,sum;
void insert(int x,int y,int z)
//cout << x <<" "<< y <<" "<< z << endl;
lst[++tot]=y; nxt[tot]=head[x]; head[x]=tot; v[tot]=z;
lst[++tot]=x; nxt[tot]=head[y]; head[y]=tot; v[tot]=0;
void bfs(int xx,int yy,int f)
memset(dis,0,sizeof(dis));
int l=1,r=2; q[1][0]=xx,q[1][1]=yy;
while(l<r)
int x=q[l][0],y=q[l++][1];
for(int i=0;i<4;i++)
int nx=x+dx[i],ny=y+dy[i];
if(s[nx][ny]=='.')
if(!dis[nx][ny])
dis[nx][ny]=dis[x][y]+1;
if(dis[nx][ny]<=f)
q[r][0]=nx,q[r++][1]=ny;
insert(id[nx][ny],id[xx][yy],1);
bool BFS()
for(int i=1;i<=W;i++)D[i]=0;D[S]=1;
int l=1,r=2;h[1]=S;
while(l<r)
int x=h[l++];
for(int i=head[x];i;i=nxt[i])
if(v[i]>0&&!D[lst[i]])
D[lst[i]]=D[x]+1;
h[r++]=lst[i];
return D[W]!=0;
int dfs(int x,int f)
int ww=0,w;
if(x==W)return f;
for(int i=head[x];i;i=nxt[i])
if(v[i]&&D[lst[i]]==D[x]+1)
w=dfs(lst[i],min(v[i],f-ww));
ww+=w;v[i]-=w,v[i^1]+=w;
if(f==ww)return ww;
return ww;
bool jud(int x)
memset(head,0,sizeof(head));tot=1;
for(int i=1;i<=top;i++)bfs(mx[i],my[i],x);
//system("pause");
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(s[i][j]=='.')insert(S,id[i][j],1);
for(int i=1;i<=top;i++)insert(id[mx[i]][my[i]],W,x);
int ans=0;
while(BFS())ans+=dfs(S,T);
return ans==sum;
int main()
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)scanf("%s",s[i]+1);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(s[i][j]!='X')
id[i][j]=++cnt;
if(s[i][j]=='D')
mx[++top]=i;
my[top]=j;
S=cnt+1,W=S+1;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(s[i][j]=='.')sum++;
int l=0,r=sum,ans=0;
while(l<=r)
int mid=(l+r)>>1;
if(jud(mid))ans=mid,r=mid-1;
else l=mid+1;
if(!ans)printf("impossible");
else cout << ans;
以上是关于BZOJ 1189: [HNOI2007]紧急疏散evacuate|网络流|二分答案的主要内容,如果未能解决你的问题,请参考以下文章
BZOJ 1189[HNOI2007]紧急疏散evacuate
[bzoj1189] [HNOI2007]紧急疏散evacuate
BZOJ1189[HNOI2007]紧急疏散evacuate 动态加边网络流
BZOJ 1189 [HNOI2007]紧急疏散evacuate