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

AC日记——[HNOI2007]紧急疏散evacuate bzoj 1189

BZOJ 1189 HNOI2007 紧急疏散evacuate