zoukankan      html  css  js  c++  java
  • HDU2732 Leapin' Lizards 网络流 最大流 SAP

    原文链接http://www.cnblogs.com/zhouzhendong/p/8362002.html


    题目传送门 - HDU2732


    题意概括

      给你一个网格,网格上的一些位置上有一只蜥蜴,所有蜥蜴的最大跳跃距离是d,如果一只蜥蜴能跳出网格边缘,那么它就安全了.且每个网格有一个最大跳出次数x,即最多有x只蜥蜴从这个网格跳出,这个网格就再也不能有蜥蜴进来了.问你最少有多少只蜥蜴跳不出网格.

    (摘自http://blog.csdn.net/u013480600/article/details/38964749)


    题解

      我们考虑到每一个点有限制经过次数,自然想到网络流。

      对于点限流,我们自然是拆点。(套路)

      于是,一个点拆成两个点,连一条边,容量为点的限流。

      我们考虑只有原来就有蜥蜴的点才能拥有初始流量,所以对于每一个有蜥蜴的点,从源点连一条容量为1的边。

      我们考虑从一个点跳到其他的点:

        如果可以直接跳出去,那自然是直接跳出去好,所以从该点向汇点连一条容量为INF的边。

        如果不能,那么流连向所有可以到达的点,容量为INF。

     

      这个输出分类很恶心,我因为no的地方加了个s而找错很久。

      主要是我一直在信心慢慢的找网络流和构图的错误……我认为我的输出一定不会错的……然后就……


    代码

    #include <cstring>
    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    #include <cstdlib>
    using namespace std;
    const int N=1005,M=N*N*3,INF=1e9;
    struct edge{
    	int x,y,cap,flow,nxt;
    };
    struct gragh{
    	int cnt,fst[N],dist[N],n,S,T,num[N],cur[N],p[N];
    	int q[N],head,tail;
    	edge e[M];
    	void set(int _S,int _T,int _n){
    		S=_S,T=_T,n=_n,cnt=1;
    		memset(fst,0,sizeof fst);
    	}
    	void add(int a,int b,int c){
    		cnt++;
    		e[cnt].x=a,e[cnt].y=b,e[cnt].cap=c,e[cnt].flow=0;
    		e[cnt].nxt=fst[a],fst[a]=cnt;
    		cnt++;
    		e[cnt].x=b,e[cnt].y=a,e[cnt].cap=0,e[cnt].flow=0;
    		e[cnt].nxt=fst[b],fst[b]=cnt;
    	}
    	void bfs(){
    		memset(dist,-1,sizeof dist);
    		head=tail=dist[T]=0;
    		q[++tail]=T;
    		while (head<tail)
    			for (int x=q[++head],y,i=fst[x];i;i=e[i].nxt)
    				if ((i&1)&&dist[y=e[i].y]==-1)
    					dist[q[++tail]=y]=dist[x]+1;
    		for (int i=1;i<=n;i++)
    			if (dist[i]==-1)
    				dist[i]=n;
    	}
    	void init(){
    		bfs();
    		memset(num,0,sizeof num);
    		for (int i=1;i<=n;i++)
    			num[dist[i]]++,cur[i]=fst[i];
    	}
    	int Augment(int &x){
    		int ex_flow=INF;
    		for (int i=T;i!=S;i=e[p[i]].x)
    			if (e[p[i]].cap-e[p[i]].flow<=ex_flow)
    				ex_flow=e[p[i]].cap-e[p[i]].flow,x=e[p[i]].x;
    		for (int i=T;i!=S;i=e[p[i]].x)
    			e[p[i]].flow+=ex_flow,e[p[i]^1].flow-=ex_flow;
    		return ex_flow;
    	}
    	int ISAP(){
    		int x=S,y,MaxFlow=0;
    		init();
    		while (dist[S]<n){
    			if (x==T){
    				MaxFlow+=Augment(x);
    				continue;
    			}
    			bool found=0;
    			for (int i=cur[x];i;i=e[i].nxt)
    				if (dist[y=e[i].y]+1==dist[x]&&e[i].cap>e[i].flow){
    					cur[x]=p[y]=i,x=y,found=1;
    					break;
    				}
    			if (!found){
    				int d=n+1;
    				for (int i=fst[x];i;i=e[i].nxt)
    					if (e[i].cap>e[i].flow)
    						d=min(d,dist[e[i].y]+1);
    				if (!--num[dist[x]])
    					return MaxFlow;
    				num[dist[x]=d]++,cur[x]=fst[x],x=x==S?x:e[p[x]].x;
    			}
    		}
    		return MaxFlow;
    	}
    }g;
    int T,n,m,d,Case=0;
    char r1[25][25],r2[25][25];
    bool Out(int x,int y){
    	return min(min(x,n+1-x),min(y,m+1-y))<=d;
    }
    int Ha(int x,int y,int in){
    	return in*n*m+(x-1)*m+y;
    }
    void solve(){
    	int S,T;
    	scanf("%d%d",&n,&d);
    	for (int i=1;i<=n;i++)
    		scanf("%s",r2[i]+1);
    	for (int i=1;i<=n;i++)
    		scanf("%s",r1[i]+1);
    	m=strlen(r1[1]+1);
    	g.set(S=n*m*2+1,T=n*m*2+2,n*m*2+2);
    	int ans=0;
    	for (int i=1;i<=n;i++)
    		for (int j=1;j<=m;j++){
    			if (r1[i][j]=='L')
    				g.add(S,Ha(i,j,0),1),ans++;
    			g.add(Ha(i,j,0),Ha(i,j,1),r2[i][j]-'0');
    		}
    	for (int i=1;i<=n;i++)
    		for (int j=1;j<=m;j++){
    			if (Out(i,j))
    				g.add(Ha(i,j,1),T,INF);
    			else
    				for (int x=1;x<=n;x++)
    					for (int y=1;y<=m;y++)
    						if ((x!=i||y!=j)&&sqrt((i-x)*(i-x)+(j-y)*(j-y))<=d)
    							g.add(Ha(i,j,1),Ha(x,y,0),INF);
    		}
    	ans-=g.ISAP();
    	printf("Case #%d: ",++Case);
    	if (ans==0)
    		printf("no lizard was left behind.
    ");
    	if (ans==1)
    		printf("1 lizard was left behind.
    ");
    	if (ans>1)
    		printf("%d lizards were left behind.
    ",ans);
    }
    int main(){
    	scanf("%d",&T);
    	while (T--)
    		solve();
    	return 0;
    }
    

      

  • 相关阅读:
    第八章:简单之美——布尔代数和搜索引擎的索引
    第六章:信息的度量和作用
    第五章:隐马尔可夫模型
    第四章谈谈中文分词
    第二章:自然语言处理———从规则到统计
    转:中文分词算法笔记
    NLTK之WordNet 接口【转】
    sentiwordnet的简单使用
    20169202 2016-2017-2 《移动平台开发实践》实验总结--七周
    20169202 2016-2017-2《移动平台》第七周学习总结
  • 原文地址:https://www.cnblogs.com/zhouzhendong/p/HDU2732.html
Copyright © 2011-2022 走看看