【Codeforces Round #185】Codeforces 311E Biologist

生物学家SmallR研发了一项可以改变狗性别的技术,并计划通过满足富人们的特殊要求来获得经济回报。为了确保收益最大化并考虑到可能的赔款,需要进行复杂的计算。本文将介绍如何通过一种特殊的算法来解决这一问题。
摘要由CSDN通过智能技术生成

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.

每个动物分别向源或汇连边,割开表示改变性别。
先把所有收益累计,再减掉违反费用。以源为例,从源向需求连任务为收益的边,割掉表示不取这个任务。从任务向对应的动物连正无穷的边,表示如果选了任务必须选这些动物。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int s=20005,t=20006,oo=0x3f3f3f3f;
int fir[20010],ne[100010],to[100010],w[100010],
c[10010],f[20010],que[20010],
n,m,num;
void add(int u,int v,int x)
{
    num++;
    ne[num*2]=fir[u];
    fir[u]=num*2;
    to[num*2]=v;
    w[num*2]=x;
    ne[num*2+1]=fir[v];
    fir[v]=num*2+1;
    to[num*2+1]=u;
    w[num*2+1]=0;
}
bool bfs()
{
    int u,v,hd=1,tl=1;
    for (int i=1;i<=n+m;i++) f[i]=0;
    f[t]=0;
    f[s]=1;
    que[1]=s;
    while (hd<=tl)
    {
        u=que[hd++];
        for (int i=fir[u];i;i=ne[i])
            if (!f[v=to[i]]&&w[i])
            {
                f[v]=f[u]+1;
                que[++tl]=v;
            }
    }
    return f[t];
}
int dfs(int u,int lim)
{
    int v,x,ret=0;
    if (u==t) return lim;
    for (int i=fir[u];i&&ret<lim;i=ne[i])
        if (f[v=to[i]]==f[u]+1&&w[i])
        {
            x=dfs(v,min(lim-ret,w[i]));
            ret+=x;
            w[i]-=x;
            w[i^1]+=x;
        }
    if (!ret) f[u]=0;
    return ret;
}
void check()
{
    for (int i=1;i<=t;i++)
        for (int j=fir[i];j;j=ne[j])
            if (w[j]) printf("%d->%d:%d\n",i,to[j],w[j]);
}
int main()
{
    int k,u,v,x,y,w,g,ans=0;
    scanf("%d%d%d",&n,&m,&g);
    for (int i=1;i<=n;i++)
        scanf("%d",&c[i]);
    for (int i=1;i<=n;i++)
    {
        scanf("%d",&x);
        if (c[i]) add(i,t,x);
        else add(s,i,x);
    }
    for (int i=1;i<=m;i++)
    {
        scanf("%d%d%d",&x,&w,&k);
        ans+=w;
        while (k--)
        {
            scanf("%d",&y);
            if (x) add(y,i+n,oo);
            else add(i+n,y,oo);
        }
        scanf("%d",&y);
        if (x) add(i+n,t,w+y*g);
        else add(s,i+n,w+y*g);
    }
    //check();
    while (bfs()) while (x=dfs(s,oo)) ans-=x;
    printf("%d\n",ans);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值