[BZOJ1565]植物大战僵尸

Posted jefflyy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[BZOJ1565]植物大战僵尸相关的知识,希望对你有一定的参考价值。

如果$x$可以攻击$y$,那么选了$y$就一定要选$x$,并且选了$x$就一定要选$x$右边的格子,格子还有权值,这就是最大权闭合子图的模型了,但是注意到图中可能存在环,直接拓扑排序忽略环即可

#include<stdio.h>
#include<string.h>
const int inf=100000000;
int min(int a,int b){return a<b?a:b;}
namespace g1{
	int h[610],nex[600010],to[600010],d[610],q[600010],M,n;
	bool ok[610];
	void add(int a,int b){
		M++;
		to[M]=b;
		d[b]++;
		nex[M]=h[a];
		h[a]=M;
	}
	void sort(){
		int head,tail,x,i;
		head=1;
		tail=0;
		for(i=1;i<=n;i++){
			if(d[i]==0){
				tail++;
				q[tail]=i;
				ok[i]=1;
			}
		}
		while(head<=tail){
			x=q[head];
			head++;
			for(i=h[x];i;i=nex[i]){
				d[to[i]]--;
				if(d[to[i]]==0){
					tail++;
					q[tail]=to[i];
					ok[to[i]]=1;
				}
			}
		}
	}
}
namespace g2{
	int h[610],cur[610],to[2000010],nex[2000010],cap[2000010],dis[610],q[2000010],M=1,S,T;
	void add(int a,int b,int c){
		M++;
		to[M]=b;
		cap[M]=c;
		nex[M]=h[a];
		h[a]=M;
		M++;
		to[M]=a;
		cap[M]=0;
		nex[M]=h[b];
		h[b]=M;
	}
	bool bfs(){
		int head,tail,x,i;
		memset(dis,-1,sizeof(dis));
		head=tail=1;
		q[1]=S;
		dis[S]=0;
		while(head<=tail){
			x=q[head];
			head++;
			for(i=h[x];i;i=nex[i]){
				if(cap[i]&&dis[to[i]]==-1){
					dis[to[i]]=dis[x]+1;
					if(to[i]==T)return 1;
					tail++;
					q[tail]=to[i];
				}
			}
		}
		return 0;
	}
	int dfs(int x,int flow){
		if(x==T)return flow;
		int i,f;
		for(i=cur[x];i;i=nex[i]){
			if(cap[i]&&dis[to[i]]==dis[x]+1){
				f=dfs(to[i],min(flow,cap[i]));
				if(f){
					cap[i]-=f;
					cap[i^1]+=f;
					if(cap[i])cur[x]=i;
					return f;
				}
			}
		}
		dis[x]=-1;
		return 0;
	}
	int dicnic(){
		int ans,tmp;
		ans=0;
		while(bfs()){
			memcpy(cur,h,sizeof(h));
			while(tmp=dfs(S,inf))ans+=tmp;
		}
		return ans;
	}
}
int n,m,v[610];
int tr(int x,int y){return(x-1)*m+y;}
using namespace g1;
int main(){
	int i,j,t,x,y,sum;
	scanf("%d%d",&::n,&m);
	g1::n=::n*m;
	for(i=1;i<=g1::n;i++){
		scanf("%d%d",v+i,&t);
		while(t--){
			scanf("%d%d",&x,&y);
			add(i,tr(x+1,y+1));
		}
	}
	for(i=1;i<=::n;i++){
		for(j=1;j<m;j++)add(tr(i,j+1),tr(i,j));
	}
	sort();
	using g2::S;
	using g2::T;
	using g2::add;
	using g1::n;
	S=n+1;
	T=n+2;
	sum=0;
	for(x=1;x<=n;x++){
		if(ok[x]){
			if(v[x]>0){
				sum+=v[x];
				add(S,x,v[x]);
			}else if(v[x]<0)
				add(x,T,-v[x]);
			for(i=h[x];i;i=nex[i]){
				if(ok[to[i]])add(to[i],x,inf);
			}
		}
	}
	printf("%d",sum-g2::dicnic());
}

以上是关于[BZOJ1565]植物大战僵尸的主要内容,如果未能解决你的问题,请参考以下文章

[bzoj1565][NOI2009]植物大战僵尸_网络流_拓扑排序

BZOJ 1565: [NOI2009]植物大战僵尸

BZOJ 1565: [NOI2009]植物大战僵尸

bzoj1565NOI2009植物大战僵尸

BZOJ1565 植物大战僵尸

[bzoj1565]植物大战僵尸