• [BZOJ3438][洛谷P1361]小M的作物


    题目大意:
    有A、B两个集合和n个物品,每个物品只能放在一个集合里。每个物品放在不同集合内能获得不同价值。
    有一些物品,如果它们同时放在一个集合内,则会产生新的价值(A和B中都有且不一定相同(c1和c2))。有若干这样的关系。
    现在让你求最大总价值。
    解题思路:
    最大权闭合子图。
    首先拆点,把点i拆成xi和yi
    从S向每个xi连容量为“其放在集合A中的价值”的边,从xi向yi连容量为inf的边,从yi向T连容量为“其放在集合B中的价值”的边。
    对于每个关系,新建节点p1,p2。从S向p1连容量为c1的边,从p1向每个有关系的y点连容量为inf的边;从p2向T连容量为c2的边,从每个有关系的x点向p2连容量为inf的边。
    然后用总价值(包括关系中的c1和c2)减去最小割即可。

    C++ Code:

    #include<cstdio>
    #include<cctype>
    #include<cstring>
    #include<queue>
    const int S=0,T=40003,inf=0x3fffffff;
    inline int readint(){
    	int c=getchar(),d=0;
    	for(;!isdigit(c);c=getchar());
    	for(;isdigit(c);c=getchar())
    	d=(d<<3)+(d<<1)+(c^'0');
    	return d;
    }
    int n,m,head[40333],cnt=1,level[40333],iter[40333],mrsrz,nx[40333];
    struct edge{
    	int to,nxt,cap;
    }e[1700005];
    inline void addedge(int u,int v,int t){
    	e[++cnt]=(edge){v,head[u],t};
    	head[u]=cnt;
    	e[++cnt]=(edge){u,head[v],0};
    	head[v]=cnt;
    }
    std::queue<int>q;
    void bfs(){
    	level[S]=1;
    	for(q.push(S);!q.empty();){
    		int u=q.front();
    		q.pop();
    		for(int i=head[u];~i;i=e[i].nxt)
    		if(e[i].cap&&!~level[e[i].to]){
    			level[e[i].to]=level[u]+1;
    			q.push(e[i].to);
    		}
    	}
    }
    inline int min(int a,int b){return a<b?a:b;}
    int dfs(int u,int f){
    	if(!f||u==T)return f;
    	for(int& i=iter[u];~i;i=e[i].nxt)
    	if(e[i].cap&&level[e[i].to]>level[u]){
    		int d=dfs(e[i].to,min(f,e[i].cap));
    		if(d){
    			e[i].cap-=d;
    			e[i^1].cap+=d;
    			return d;
    		}else level[e[i].to]=-1;
    	}
    	return 0;
    }
    int dinic(){
    	for(int flow=0,f;;){
    		memset(level,-1,sizeof nx);
    		if(bfs(),!~level[T])return flow;
    		memcpy(iter,head,sizeof nx);
    		while(f=dfs(S,inf))flow+=f;
    	}
    }
    int main(){
    	#ifdef LOCALJUDGE
    	freopen("input.txt","r",stdin);
    	#endif
    	int ans=0;
    	memset(head,-1,sizeof head);
    	n=readint();
    	for(int i=1;i<=n;++i){
    		int p=readint();
    		ans+=p;
    		addedge(S,i,p);
    	}
    	for(int i=1;i<=n;++i)addedge(i,i+n,inf);
    	for(int i=1;i<=n;++i){
    		int p=readint();
    		ans+=p;
    		addedge(i+n,T,p);
    	}
    	mrsrz=n<<1;
    	for(int k=readint();k--;){
    		int m=readint(),c1=readint(),c2=readint();
    		ans+=c1+c2;
    		for(int i=1;i<=m;++i)nx[i]=readint();
    		addedge(S,++mrsrz,c1);
    		for(int i=1;i<=m;++i)addedge(mrsrz,nx[i],inf);
    		addedge(++mrsrz,T,c2);
    		for(int i=1;i<=m;++i)addedge(nx[i],mrsrz,inf);
    	}
    	printf("%d
    ",ans-dinic());
    	return 0;
    }
    
  • 相关阅读:
    差分约束系统
    LCA
    CRB and Candies LCM 性质
    【强连通分量】 Kosaraju和Tarjan算法 (标准模板+详细注释)
    最小生成树
    堆优化的迪杰斯特拉算法
    SPFA算法
    Floyd算法
    Dijkstra算法
    图论中环的判断
  • 原文地址:https://www.cnblogs.com/Mrsrz/p/9291222.html
Copyright © 2020-2023  润新知