zoukankan      html  css  js  c++  java
  • 【BZOJ1565】【NOI2009】植物大战僵尸 网络流 最大权闭合子图

    题目大意

    ​  给你一个(n imes m)的地图,每个格子上都有一颗植物,有的植物能保护其他植物。僵尸从右往左进攻,每吃掉一颗植物就可以得到(a_{i,j})的收益((a_{i,j})可以是负数)。求僵尸的最大收益

    ​  (1leq nleq20,1leq mleq30)

    题解

    ​  这种一个东西可以保护另一个东西而且数据范围那么小的题目显然是最大权闭合子图。

    ​  僵尸从右往左进攻,所以一棵植物可以保护它左边的植物。

    ​  如果保护关系形成一个环,就都不能选。

    ​  直接套模板即可。

    ​  可能需要一些优化

    代码

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cstdlib>
    #include<ctime>
    #include<utility>
    #include<queue>
    using namespace std;
    typedef long long ll;
    typedef pair<int,int> pii;
    struct list
    {
    	int v[1000010];
    	int w[1000010];
    	int t[1000010];
    	int h[1010];
    	int n;
    	list()
    	{
    		memset(h,0,sizeof h);
    		n=0;
    	}
    	void add(int x,int y,int z)
    	{
    		n++;
    		v[n]=y;
    		w[n]=z;
    		t[n]=h[x];
    		h[x]=n;
    	}
    };
    list l,l2;
    void add(int x,int y,int z)
    {
    	l.add(x,y,z);
    	l.add(y,x,0);
    }
    int n,m;
    int w[110][110];
    int gx[1010];
    int gy[1010];
    int id(int x,int y)
    {
    	return (x-1)*m+y;
    }
    int vis[1010];
    int b[1010];
    void dfs(int x)
    {
    	vis[x]=1;
    	int i;
    	for(i=l2.h[x];i;i=l2.t[i])
    	{
    		if(!vis[l2.v[i]])
    			dfs(l2.v[i]);
    		if(b[l2.v[i]]||vis[l2.v[i]]==1)
    		{
    //			w[gx[x]][gy[x]]=-10000000;
    			b[x]=1;
    		}
    	}
    	vis[x]=2;
    }
    int d[1010];
    int S,T;
    int c[30][40][30][40];
    int bfs()
    {
    	memset(d,-1,sizeof d);
    	queue<int> q;
    	q.push(S);
    	d[S]=0;
    	int x,i;
    	while(!q.empty())
    	{
    		x=q.front();
    		q.pop();
    		for(i=l.h[x];i;i=l.t[i])
    			if(l.w[i]&&d[l.v[i]]==-1)
    			{
    				d[l.v[i]]=d[x]+1;
    				if(l.v[i]==T)
    					return 1;
    				q.push(l.v[i]);
    			}
    	}
    	return 0;
    }
    int op(int x)
    {
    	return ((x-1)^1)+1;
    }
    int dfs(int x,int flow)
    {
    	if(x==T)
    		return flow;
    	int c,s=0,i;
    	for(i=l.h[x];i;i=l.t[i])
    		if(l.w[i]&&d[l.v[i]]==d[x]+1)
    		{
    			c=dfs(l.v[i],min(flow,l.w[i]));
    			s+=c;
    			flow-=c;
    			l.w[i]-=c;
    			l.w[op(i)]+=c;
    			if(!flow)
    				break;
    		}
    	if(flow)
    		d[x]=-1;
    	return s;
    }
    int main()
    {
    	memset(b,0,sizeof b);
    	memset(c,0,sizeof c);
    //	freopen("bzoj1565.in","r",stdin);
    //	freopen("bzoj1565.out","w",stdout);
    	scanf("%d%d",&n,&m);
    	S=n*m+1;
    	T=S+1;
    	int sum=0;
    	int i,j,k,o,x,y,u;
    	for(i=1;i<=n;i++)
    		for(j=1;j<=m;j++)
    		{
    			scanf("%d",&w[i][j]);
    			gx[id(i,j)]=i;
    			gy[id(i,j)]=j;
    			scanf("%d",&u);
    			for(k=1;k<=u;k++)
    			{
    				scanf("%d%d",&x,&y);
    				x++;
    				y++;
    				c[i][j][x][y]=1;
    			}
    			if(j>1)
    				c[i][j][i][j-1]=1;
    			for(x=1;x<=n;x++)
    				for(y=1;y<=m;y++)
    					if(c[i][j][x][y])
    						l2.add(id(x,y),id(i,j),0);
    		}
    	memset(vis,0,sizeof vis);
    	for(i=1;i<=n;i++)
    		for(j=1;j<=m;j++)
    			if(!vis[id(i,j)])
    				dfs(id(i,j));
    	for(i=1;i<=n;i++)
    		for(j=1;j<=m;j++)	
    			if(!b[id(i,j)])
    			{
    				if(w[i][j]>0)
    				{
    					sum+=w[i][j];
    					add(S,id(i,j),w[i][j]);
    				}
    				else
    					add(id(i,j),T,-w[i][j]);
    				for(x=1;x<=n;x++)
    					for(y=1;y<=m;y++)
    						if(c[i][j][x][y])
    							if(!b[id(x,y)])
    								add(id(x,y),id(i,j),0x7fffffff);
    			}
    	int ans=0;
    	while(bfs())
    		ans+=dfs(S,0x7fffffff);
    	printf("%d
    ",sum-ans);
    	return 0;
    }
    
  • 相关阅读:
    abap程序之间调用
    java-response-乱码解决
    java-servlet:response/request
    同平台不允许同时登陆的方案(不同平台可同时登陆)
    @Async 异步http请求,汇总数据处理
    ABAP-VOFM FOR MM-PO PRICE
    ABAP-CDS
    PI-Custom adapter module
    Vue中在移动端如何判断设备是安卓还是ios
    v-show在select中选择bug
  • 原文地址:https://www.cnblogs.com/ywwyww/p/8510677.html
Copyright © 2011-2022 走看看