[codeforces311E]Biologist

SmallR is a biologist. Her latest research finding is how to change the sex of dogs. In other words, she can change female dogs into male dogs and vice versa.

She is going to demonstrate this technique. Now SmallR has n dogs, the costs of each dog’s change may be different. The dogs are numbered from 1 to n. The cost of change for dog i is vi RMB. By the way, this technique needs a kind of medicine which can be valid for only one day. So the experiment should be taken in one day and each dog can be changed at most once.

This experiment has aroused extensive attention from all sectors of society. There are m rich folks which are suspicious of this experiment. They all want to bet with SmallR forcibly. If SmallR succeeds, the i-th rich folk will pay SmallR wi RMB. But it’s strange that they have a special method to determine whether SmallR succeeds. For i-th rich folk, in advance, he will appoint certain ki dogs and certain one gender. He will think SmallR succeeds if and only if on some day the ki appointed dogs are all of the appointed gender. Otherwise, he will think SmallR fails.

If SmallR can’t satisfy some folk that isn’t her friend, she need not pay him, but if someone she can’t satisfy is her good friend, she must pay g RMB to him as apologies for her fail.

Then, SmallR hope to acquire money as much as possible by this experiment. Please figure out the maximum money SmallR can acquire. By the way, it is possible that she can’t obtain any money, even will lose money. Then, please give out the minimum money she should lose.

Input
The first line contains three integers n, m, g (1 ≤ n ≤ 104, 0 ≤ m ≤ 2000, 0 ≤ g ≤ 104). The second line contains n integers, each is 0 or 1, the sex of each dog, 0 represent the female and 1 represent the male. The third line contains n integers v1, v2, …, vn (0 ≤ vi ≤ 104).

Each of the next m lines describes a rich folk. On the i-th line the first number is the appointed sex of i-th folk (0 or 1), the next two integers are wi and ki (0 ≤ wi ≤ 104, 1 ≤ ki ≤ 10), next ki distinct integers are the indexes of appointed dogs (each index is between 1 and n). The last number of this line represents whether i-th folk is SmallR’s good friend (0 — no or 1 — yes).

Output
Print a single integer, the maximum money SmallR can gain. Note that the integer is negative if SmallR will lose money.

分析

这种题一看就像网络流。
首先答案可以等于 w -不要的w-变性花费的v-花费的g
要使减去的东西最小,可以考虑用最小割。
关键在于如何连边?
首先考虑每只dog。如果它是雄性的,就让它向汇点连一条容量为vi的边,否则原点向它连一条容量为vi的边。
现在考虑每个人。如果他要求的性别是雄性,那么他要求的dog向他连一条无穷大的边,然后他向汇点连一条容量为w(+g)的边。这样连接表示:如果保留这条边,即满足这个人的要求,那么与他相连的每只dog都要割掉与s相连的边(即变成雄性)。同理,如果他要求的是雌性,那么他向要求的dog连一条无穷大的边,然后原点向他连一条容量为w(+g)的边。

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int maxn=12005,maxm=100005,inf=1e9;

int n,m,g,tot,ans,t,h[maxn],e[maxm],next[maxm],fl[maxm],ch[maxm],f[maxn],now[maxn],visit[maxn],seq[15];

bool bz[maxn];

void add(int x,int y,int f,int o)
{
    e[++tot]=y; next[tot]=h[x]; fl[tot]=f; ch[tot]=tot+o; h[x]=tot;
}

int aug(int x,int flow)
{
    visit[x]=tot;
    if (x==t) return flow;
    for (int i=now[x];i;i=next[i])
    {
        if (fl[i] && f[x]==f[e[i]]+1 && visit[e[i]]<tot)
        {
            int tmp=aug(e[i],min(flow,fl[i]));
            if (tmp)
            {
                fl[i]-=tmp;
                fl[ch[i]]+=tmp;
                now[x]=i;
                return tmp;
            }
        }
    }
    return now[x]=0;
}

void flow()
{
    memcpy(now,h,sizeof(now));
    while (1)
    {
        tot++;
        int tmp=aug(0,inf);
        if (!tmp) break;
        ans-=tmp;
    }
}

bool check()
{
    int tmp=inf;
    for (int i=0;i<=t;i++) if (visit[i]==tot)
    {
        for (int j=h[i];j;j=next[j])
        {
            if (fl[j] && visit[e[j]]<tot && tmp>f[e[j]]+1-f[i])
            {
                tmp=f[e[j]]+1-f[i];
            }
        }
    }
    if (tmp==inf) return 0;
    for (int i=0;i<=t;i++) if (visit[i]==tot) f[i]+=tmp;
    return 1;
}

int main()
{
    scanf("%d%d%d",&n,&m,&g);
    t=n+m+1;
    for (int i=1;i<=n;i++) scanf("%d",&bz[i]);
    for (int i=1;i<=n;i++)
    {
        int w;
        scanf("%d",&w);
        if (bz[i])
        {
            add(i,t,w,1); add(t,i,0,-1);
        }else
        {
            add(0,i,w,1); add(i,0,0,-1);
        }
    }
    for (int i=1;i<=m;i++)
    {
        int sex,w,k,p;
        scanf("%d%d%d",&sex,&w,&k);
        for (int j=0;j<k;j++) scanf("%d",&seq[j]);
        scanf("%d",&p);
        if (sex)
        {
            for (int j=0;j<k;j++)
            {
                add(seq[j],n+i,inf,1); add(n+i,seq[j],0,-1);
            }
            add(n+i,t,w+p*g,1); add(t,n+i,0,-1);
        }else
        {
            for (int j=0;j<k;j++)
            {
                add(n+i,seq[j],inf,1); add(seq[j],n+i,0,-1);
            }
            add(0,n+i,w+p*g,1); add(n+i,0,0,-1);
        }
        ans+=w;
    }
    tot=0;
    for (flow();check();flow());
    printf("%d\n",ans);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值