zoukankan      html  css  js  c++  java
  • LOJ6045 价

    人类智慧之神zhangzj最近有点胖,所以要减肥,他买了(N)种减肥药,发现每种减肥药使用了若干种药材,总共正好有(N)种不同的药材。

    经过他的人脑实验,他发现如果他吃下去了(K~(0leq Kleq N))种减肥药,而这(K)种减肥药使用的药材并集大小也为(K),这(K)种才会有效果,否则无效。

    (i)种减肥药在产生效果的时候会使zhangzj的体重增加(P_i)斤,显然(P_i)可以小于(0)

    他想知道,一次吃药最好情况下体重变化量是多少,当然可以一种药也不吃,此时体重不变。

    由于某些奥妙重重的情况,我们可以让这(N)种减肥药每一种对应一个其使用的药材,且(N)种减肥药对应的药材互不相同(即有完美匹配)。

    对于(100\%)的数据,(1 leq N leq 300,~|P_i| leq 1000000)

    题解

    把减肥药的权值设成(-P_i+inf),把药材的权值设成(-inf),然后看成最大权闭合子点集中间连(infty)的边,跑个最小割就能得出答案了。

    会不会出现选了(x)种减肥药,并且对应了(y~(y>x))种药材的情况呢?如果出现了的话,因为(y imesinf>x imes(-P_i+infty)),所以左侧一定割断了至少一条边。对应最大权闭合子点集的意义,那么左侧一定有至少一种减肥药没有被选,与假设矛盾。所以不存在这种情况,正确性有保证。

    CO int64 inf=1e18,mx=1e9;
    CO int N=1e3;
    namespace Flow{
    	int S,T;
    	struct edge {int v;int64 c;int a;};
    	vector<edge> to[N];
    	int dis[N];
    	
    	IN void init(int n){
    		S=n-1,T=n;
    	}
    	IN void link(int u,int v,int64 c){
    		to[u].push_back({v,c}),to[v].push_back({u,0});
    		to[u].back().a=to[v].size()-1,to[v].back().a=to[u].size()-1;
    	}
    	bool bfs(){
    		fill(dis+1,dis+T+1,-1),dis[T]=0;
    		deque<int> Q={T};
    		while(Q.size()){
    			int u=Q.front();Q.pop_front();
    			for(CO edge&e:to[u])
    				if(to[e.v][e.a].c and dis[e.v]==-1){
    					dis[e.v]=dis[u]+1;
    					Q.push_back(e.v);
    				}
    		}
    		return dis[S]!=-1;
    	}
    	int64 dfs(int u,int64 lim){
    		if(u==T) return lim;
    		int64 rest=lim;
    		for(edge&e:to[u])
    			if(e.c and dis[e.v]==dis[u]-1){
    				int delta=dfs(e.v,min(e.c,rest));
    				if(!delta) {dis[e.v]=-1; continue;}
    				rest-=delta,e.c-=delta,to[e.v][e.a].c+=delta;
    				if(!rest) break;
    			}
    		return lim-rest;
    	}
    	int64 main(){
    		int64 ans=0;
    		while(bfs()) ans+=dfs(S,inf);
    		return ans;
    	}
    }
    
    int main(){
    	int n=read<int>();
    	Flow::init(2*n+2);
    	for(int i=1;i<=n;++i)for(int t=read<int>();t--;)
    		Flow::link(i,n+read<int>(),inf);
    	int64 ans=0;
    	for(int i=1;i<=n;++i){
    		int64 p=read<int64>();
    		Flow::link(Flow::S,i,mx-p);
    		ans+=mx-p;
    		Flow::link(n+i,Flow::T,mx);
    	}
    	ans-=Flow::main();
    	printf("%lld
    ",-ans);
    	return 0;
    }
    
  • 相关阅读:
    Linux基操:软件安装的方式:解压缩安装
    Linux基操:linux命令失效解决方法
    Linux基操:软件安装的方式:rpm,&&环境变量配置
    Linux基操:进程管理
    Linux基操:磁盘管理,扩展文件挂载问题
    Linux基操(Centos7):用户管理
    Linux基操:文件内容查看方式&&软链接硬链接(拓展)
    Linux基操:目录相关命令
    多测师肖sir_高级金牌讲师__面试和答案归纳
    多测师肖sir__高级金牌讲师 ___python中len函数
  • 原文地址:https://www.cnblogs.com/autoint/p/12788782.html
Copyright © 2011-2022 走看看