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.\n");
	if (ans==1)
		printf("1 lizard was left behind.\n");
	if (ans>1)
		printf("%d lizards were left behind.\n",ans);
}
int main(){
	scanf("%d",&T);
	while (T--)
		solve();
	return 0;
}

  

posted @ 2018-01-26 23:28  zzd233  阅读(276)  评论(0编辑  收藏  举报