码迷,mamicode.com
首页 > 其他好文 > 详细

[CF311E]Biologist

时间:2018-04-04 18:22:03      阅读:208      评论:0      收藏:0      [点我收藏+]

标签:pac   ble   body   problem   \n   tps   inf   har   href   

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\n",ans-Dinic());
    return 0;
}

[CF311E]Biologist

标签:pac   ble   body   problem   \n   tps   inf   har   href   

原文地址:https://www.cnblogs.com/zhoushuyu/p/8718060.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!