[CF311E]Biologist

luogu

题意

(n)(01)变量,你要确定它们的值,改变第(i)个变量的代价是(v_i)
(m)个限制条件,每个形如:某个变量集合内的所有元素都必须是(0),或者都必须是(1)。达成这个条件会获得(W_i)的收益,否则有可能会付出(g)的代价。
求最大收益。

sol

最大权闭合子图。转化成总收益减去最小损失来做。
最小割。假设(S)这边的都是(0)(T)这边的都是(1)
(n)个变量(n)个点,然后每个限制条件建一个点。
对于一个原本是(0)的变量,连边((S,i,v_i)),否则连边((i,T,v_i))
对于一个限制,如果要求全都必须是(0),那么也就是说只要有一个(1)就算作不满足。集合内的所有元素连边((i+n,x,inf)),然后连边((S,i+n,W_i))。这样子只要存在一个变量取了(1),这个点一定会被割在(T)这边,然后(W_i)就被算进割集里去了。
注意上述的边都是单向边。也就是说,不能存在从(S)跨越到(T)(inf)边,但是从(T)跨越到(S)(inf)边则是允许的。
要求全部是(1)同理,对每个元素连边((x,i+n,inf)),然后连边((i+n,T,W_i))即可。
(g)的损失直接加到(W_i)里面去就好了。

code

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
int gi()
{
	int x=0,w=1;char ch=getchar();
	while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
	if (ch=='-') w=0,ch=getchar();
	while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
	return w?x:-x;
}
const int N = 15000;
const int inf = 1e9;
struct edge{int to,nxt,w;}a[N*10];
int n,m,g,sex[N],S,T,head[N],cnt=1,dep[N],cur[N],ans;
queue<int>Q;
void link(int u,int v,int w)
{
	a[++cnt]=(edge){v,head[u],w};
	head[u]=cnt;
	a[++cnt]=(edge){u,head[v],0};
	head[v]=cnt;
}
bool bfs()
{
	memset(dep,0,sizeof(dep));
	dep[S]=1;Q.push(S);
	while (!Q.empty())
	{
		int u=Q.front();Q.pop();
		for (int e=head[u];e;e=a[e].nxt)
			if (a[e].w&&!dep[a[e].to])
				dep[a[e].to]=dep[u]+1,Q.push(a[e].to);
	}
	return dep[T];
}
int dfs(int u,int f)
{
	if (u==T) return f;
	for (int &e=cur[u];e;e=a[e].nxt)
		if (a[e].w&&dep[a[e].to]==dep[u]+1)
		{
			int tmp=dfs(a[e].to,min(a[e].w,f));
			if (tmp) {a[e].w-=tmp;a[e^1].w+=tmp;return tmp;}
		}
	return 0;
}
int Dinic()
{
	int res=0;
	while (bfs())
	{
		for (int i=1;i<=T;++i) cur[i]=head[i];
		while (int tmp=dfs(S,inf)) res+=tmp;
	}
	return res;
}
int main()
{
	n=gi();m=gi();g=gi();S=n+m+1;T=S+1;
	for (int i=1;i<=n;++i) sex[i]=gi();
	for (int i=1;i<=n;++i)
	{
		int x=gi();
		sex[i]?link(i,T,x):link(S,i,x);
	}
	for (int i=1;i<=m;++i)
	{
		int v=gi(),w=gi(),k=gi();ans+=w;
		while (k--)
		{
			int x=gi();
			v?link(x,i+n,inf):link(i+n,x,inf);
		}
		int gg=gi();w+=g*gg;
		v?link(i+n,T,w):link(S,i+n,w);
	}
	printf("%d
",ans-Dinic());
	return 0;
}
原文地址:https://www.cnblogs.com/zhoushuyu/p/8718060.html