ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

CF103E Buying Sets

2021-10-05 13:31:06  阅读:192  来源: 互联网

标签:fir long int 权值 tot 子集 Buying Sets CF103E


https://www.luogu.com.cn/problem/CF103E

有一个大小为 \(n\) 的全集,每个元素是一个数,有 \(n\) 个子集。题目保证任意 \(k\) 个子集的并的大小 \(\ge k\)。
每个子集有一个可正可负的权值,你需要选出一些子集使得这些子集并的大小等于子集个数,且所选子集的权值和最小。可以为空集。

考虑权值取负,然后变成最大化权值
考虑建模使得 \(S\) 连到集合边权为权值,集合连到数边权无穷,数连到 \(T\) 边权 \(0\)
这样割掉 \(S\) 的边即为不选某个集合,割掉 \(T\) 的边就是选某个数

由于任意 \(k\) 个子集的并的大小 \(\ge k\),可得割掉的边的数量一定不小于 \(n\)
证明大概是,设左边割掉的集合为 \(L\),右边为 \(R\),则 \(\complement L\) 所连向的右边的点的集合只能是 \(R\)
则有 \(|\complement L|\le |R|\Rightarrow n-L\le R\Rightarrow n\le L+R\)

但是要求 不选的集合和选的数 的个数相等,则可以让 \(S\) 连的边变成无穷加权值,\(T\) 连的边变成无穷,这样不会再割多余的边,就有了 \(L+R=n\)

#define N 606
#define M 360006
struct Graph{
	int fir[N],fir_[N],nex[M],to[M],tot;
	long long w[M];
	inline void add(int u,int v,long long W,int flag=1){
		if(!tot) tot=1;
		to[++tot]=v;w[tot]=W;
		nex[tot]=fir[u];fir[u]=tot;
		if(flag) add(v,u,0,0);
	}
}G;
int S,T;
int deep[N];
int left,right,que[N];
inline int bfs(){
	std::memset(deep,0,sizeof deep);
	left=right=0;
	que[0]=S;deep[S]=1;
	int u;
	while(left<=right){
		u=que[left++];
		for(int v,i=G.fir[u];i;i=G.nex[i]){
			v=G.to[i];
			if(deep[v]||!G.w[i]) continue;
			deep[v]=deep[u]+1;que[++right]=v;
			if(v==T) return 1;
		}
	}
	return 0;
}
long long dfs(int u,long long now=1e18){
	if(u==T) return now;
	long long res=now;
	for(int v,&i=G.fir_[u];i;i=G.nex[i]){
		v=G.to[i];
		if(deep[v]!=deep[u]+1||!G.w[i]) continue;
		long long k=dfs(v,std::min(res,G.w[i]));
		if(!k) deep[v]=0;
		else G.w[i]-=k,G.w[i^1]+=k,res-=k;
		if(!res) break;
	}
	return now-res;
}
inline long long dinic(){
	long long ans=0;
	while(bfs()){
		long long now;
		std::memcpy(G.fir_,G.fir,sizeof G.fir);
		while(now=dfs(S)) ans+=now;
	}
	return ans;
}
int main(){
	int n=read();
	S=n+n+1;T=S+1;
	for(int k,i=1;i<=n;i++){
		k=read();
		while(k--) G.add(i,n+read(),LL_INF);
		G.add(n+i,T,LL_INF);
	}
	long long sum=0;
	for(int k,i=1;i<=n;i++){
		k=-read();sum+=k;
		G.add(S,i,LL_INF+k);
	}
	long long ans=dinic()-n*LL_INF;
	printf("%d\n",ans-sum);
	return 0;
}

标签:fir,long,int,权值,tot,子集,Buying,Sets,CF103E
来源: https://www.cnblogs.com/suxxsfe/p/15368489.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有