zoukankan      html  css  js  c++  java
  • 【BZOJ3438】小M的作物 最小割

    【BZOJ3438】小M的作物

    Description

    小M在MC里开辟了两块巨大的耕地A和B(你可以认为容量是无穷),现在,小P有n中作物的种子,每种作物的种子
    有1个(就是可以种一棵作物)(用1...n编号),现在,第i种作物种植在A中种植可以获得ai的收益,在B中种植
    可以获得bi的收益,而且,现在还有这么一种神奇的现象,就是某些作物共同种在一块耕地中可以获得额外的收益
    ,小M找到了规则中共有m种作物组合,第i个组合中的作物共同种在A中可以获得c1i的额外收益,共同总在B中可以
    获得c2i的额外收益,所以,小M很快的算出了种植的最大收益,但是他想要考考你,你能回答他这个问题么?

    Input

    第一行包括一个整数n
    第二行包括n个整数,表示ai第三行包括n个整数,表示bi第四行包括一个整数m接下来m行,
    对于接下来的第i行:第一个整数ki,表示第i个作物组合中共有ki种作物,
    接下来两个整数c1i,c2i,接下来ki个整数,表示该组合中的作物编号。输出格式

    Output

    只有一行,包括一个整数,表示最大收益

    Sample Input

    3
    4 2 1
    2 3 2
    1
    2 3 2 1 2

    Sample Output

    11
    样例解释A耕地种1,2,B耕地种3,收益4+2+3+2=11。
    1<=k< n<= 1000,0 < m < = 1000 保证所有数据及结果不超过2*10^9。

    题解:最小割,建边方法如下:

    S->作物i,容量k1i
    作物i->T,容量k2i
    S->组合j1,容量c1j
    组合j1->组合j中的作物,容量∞
    组合j2->T,容量c2j
    组合j中的作物->j2,容量∞

    答案为总收益-最小割

     

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <queue>
    using namespace std;
    const int maxn=4010;
    const int maxm=4100000;
    int n,m,cnt,S,T,ans,sum,tot;
    int to[maxm],next[maxm],val[maxm],d[maxn],head[maxn];
    queue<int> q;
    int rd()
    {
    	int ret=0;	char gc=getchar();
    	while(gc<'0'||gc>'9')	gc=getchar();
    	while(gc>='0'&&gc<='9')	ret=ret*10+gc-'0',gc=getchar();
    	return ret;
    }
    void add(int a,int b,int c)
    {
    	to[cnt]=b,val[cnt]=c,next[cnt]=head[a],head[a]=cnt++;
    	to[cnt]=a,val[cnt]=0,next[cnt]=head[b],head[b]=cnt++;
    }
    int bfs()
    {
    	memset(d,0,sizeof(d));
    	while(!q.empty())	q.pop();
    	d[S]=1,q.push(S);
    	int i,u;
    	while(!q.empty())
    	{
    		u=q.front(),q.pop();
    		for(i=head[u];i!=-1;i=next[i])
    		{
    			if(!d[to[i]]&&val[i])
    			{
    				d[to[i]]=d[u]+1;
    				if(to[i]==T)	return 1;
    				q.push(to[i]);
    			}
    		}
    	}
    	return 0;
    }
    int dfs(int x,int mf)
    {
    	if(x==T)	return mf;
    	int i,k,temp=mf;
    	for(i=head[x];i!=-1;i=next[i])
    	{
    		if(d[to[i]]==d[x]+1&&val[i])
    		{
    			k=dfs(to[i],min(temp,val[i]));
    			if(!k)	d[to[i]]=0;
    			val[i]-=k,val[i^1]+=k,temp-=k;
    			if(!temp)	break;
    		}
    	}
    	return mf-temp;
    }
    int main()
    {
    	n=rd();
    	int i,j,k,a,b,c,d;
    	memset(head,-1,sizeof(head));
    	S=0,T=tot=n+1;
    	for(i=1;i<=n;i++)	a=rd(),add(S,i,a),sum+=a;
    	for(i=1;i<=n;i++)	a=rd(),add(i,T,a),sum+=a;
    	m=rd();
    	for(i=1;i<=m;i++)
    	{
    		a=rd();
    		b=rd(),add(S,++tot,b),sum+=b,b=rd(),add(++tot,T,b),sum+=b;
    		for(j=1;j<=a;j++)	c=rd(),add(tot-1,c,1<<30),add(c,tot,1<<30);
    	}
    	while(bfs())	ans+=dfs(S,1<<30);
    	printf("%d",sum-ans);
    	return 0;
    }

     

  • 相关阅读:
    windows下安装rabbitmq
    selectors
    修改Docker默认镜像和容器的存储位置
    eclipse配置jdk的src.zip源代码步骤
    Zookeeper WINDOWS 安装配置
    zookeeper windows 入门安装和测试
    zookeeper集群搭建(windows环境下)
    ant使用指南详细入门教程
    linux查看系统版本和系统位数
    suse linux 命令
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/6801488.html
Copyright © 2011-2022 走看看