zoukankan      html  css  js  c++  java
  • [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;
    }
    
  • 相关阅读:
    如何选择Html.RenderPartial和Html.RenderAction
    [转]使用 HTML5 WebSocket 构建实时 Web 应用
    基于.NET平台常用的框架整理
    0303
    XMLHTTP
    0120如何合并两个使用 System.Xml 使用 Visual C#.NET 的 XML 文档中的数据
    后台动态创建datatable0115
    笔记1126ASP.NET面试题(转)
    笔记1015
    数组与ARRAYLIST的关系与区别(转)
  • 原文地址:https://www.cnblogs.com/zhoushuyu/p/8718060.html
Copyright © 2011-2022 走看看