[BZOJ1565] Plants vs. Zombies

If $x$ can attack $y$, then if you choose $y$, you must choose $x$, and if you choose $x$, you must choose the grid to the right of $x$, and the grid has weights, which is the maximum The model of the weighted closed subgraph, but notice that there may be loops in the graph, the direct topological sorting can ignore the loop

#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;
		years=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());
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324614064&siteId=291194637