zoukankan      html  css  js  c++  java
  • 「BZOJ3438」小M的作物(最小割

    3438: 小M的作物

    Time Limit: 10 Sec  Memory Limit: 256 MB
    Submit: 1891  Solved: 801
    [Submit][Status][Discuss]

    Description

    小M在MC里开辟了两块巨大的耕地A和B(你可以认为容量是无穷),现在,小P有n中作物的种子,每种作物的种子
    有1个(就是可以种一棵作物)(用1...n编号),现在,第i种作物种植在A中种植可以获得ai的收益,在B中种植
    可以获得bi的收益,而且,现在还有这么一种神奇的现象,就是某些作物共同种在一块耕地中可以获得额外的收益
    ,小M找到了规则中共有m种作物组合,第i个组合中的作物共同种在A中可以获得c1i的额外收益,共同总在B中可以
    获得c2i的额外收益,所以,小M很快的算出了种植的最大收益,但是他想要考考你,你能回答他这个问题么?

    Input

    第一行包括一个整数n
    第二行包括n个整数,表示ai第三行包括n个整数,表示bi第四行包括一个整数m接下来m行,
    对于接下来的第i行:第一个整数ki,表示第i个作物组合中共有ki种作物,
    接下来两个整数c1i,c2i,接下来ki个整数,表示该组合中的作物编号。输出格式

    Output

    只有一行,包括一个整数,表示最大收益

    Sample Input

    3
    4 2 1
    2 3 2
    1
    2 3 2 1 2

    Sample Output

    11
    样例解释A耕地种1,2,B耕地种3,收益4+2+3+2=11。
    1<=k< n<= 1000,0 < m < = 1000 保证所有数据及结果不超过2*10^9。

    题解

    被洛谷大佬刷到绿了 好过分QAQ

    读了题之后就在想怎么处理组合和个体之间的不相容性。一开始打算用拆点的方法限流,然后粗略算了一下 边数会爆炸QAQ

    然后看了题解(=_=),fa现可以巧妙的用上最小割

    把源点当作A,汇点当作B,源点往每个作物连ai,作物往B连bi。

    首先对于没有组合:

    割一下,留在左边的种进A,右边的种进B,那么收益就是剩下来的边权之和。

    对于组合:

    建一个虚点,从源点连一条c1i,再往每个受它控制的点连INF;

    再建一个虚点,往汇点连一条c2i,再从每个受它控制的点连INF;

    (图是毛来的)

    其中黄边为对应值,蓝边为INF

    以下为建图合理性的证明:

    首先,INF永远割不掉。

    对于左边,如果S->c已经被割掉,也就是说c变成了B的大宝贝儿,

    想让c这条支流断掉,有两种选择:割左边的黄线,或者把右边的黄线和c->T一起割掉。

    而如果割右边的,则不符合一开始让c加入B战队的假定,且S->c割的不明不白。

    所以反证得知此时左边的黄线肯定会断。

    同理可证,如果c->T被割掉,X'到T也会断。

    ∴证得割掉组合内任意点,这个组合的群体优惠也会断掉。

    而如果某个组合的左边黄线存在,

    那么割它下面的绿线都是白割,反正过的去。

    对于右边同理。

    ∴如果某个组合优惠被得到了,那么它的所有儿砸都会留下。易知此时流量既得到了组合优惠,也收到了单个收益。

    所以这样建图是ojbk的。

    建了图然后跑个dinic算最小割,再用总边权减一下就好了。

    撒花~

    #include<cmath>
    #include<queue>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    using namespace std;
    const int INF=2*1e9+1;
    struct emm{
        int e,f,v;
    }a[2000007];
    int h[50007];
    int tot=1;
    int s,t;
    void con(int x,int y,int w)
    {
        a[++tot].f=h[x];
        h[x]=tot;
        a[tot].e=y;
        a[tot].v=w;
        a[++tot].f=h[y];
        h[y]=tot;
        a[tot].e=x;
        return;
    }
    queue<int>q;
    int d[50007];
    inline bool bfs()
    {
        memset(d,0,sizeof(d));
        d[s]=1;
        q.push(s);
        while(!q.empty())
        {
            int x=q.front();q.pop();
            for(int i=h[x];i;i=a[i].f)
            if(!d[a[i].e]&&a[i].v)
            {
                d[a[i].e]=d[x]+1;
                q.push(a[i].e);
            }
        }
        return d[t];
    }
    int dfs(int x,int al)
    {
        if(x==t||!al)return al;
        int fl=0;
        for(int i=h[x];i;i=a[i].f)
        if(d[a[i].e]==d[x]+1&&a[i].v)
        {
            int f=dfs(a[i].e,min(a[i].v,al));
            if(f)
            {
                fl+=f;
                al-=f;
                a[i].v-=f;
                a[i^1].v+=f;
                if(!al)break;
            }
        }
        if(!fl)d[x]=-1;
        return fl;
    }
    int main()
    {
        //freopen("a.in","r",stdin);
        int n;
        scanf("%d",&n);
        s=0,t=50001;
        long long all=0;
        for(int i=1;i<=n;++i)
        {
            int x;
            scanf("%d",&x);
            all+=x;
            con(s,i,x);
        }
        for(int i=1;i<=n;++i)
        {
            int x;
            scanf("%d",&x);
            all+=x;
            con(i,t,x);
        }
        int m;
        scanf("%d",&m);
        int nod=n;
        for(int i=1;i<=m;++i)
        {
            int ki,c1,c2;
            scanf("%d%d%d",&ki,&c1,&c2);
            nod++;
            con(s,nod,c1);
            con(nod+1,t,c2);
            all+=c1;
            all+=c2;
            for(int j=1;j<=ki;++j)
            {
                int x;
                scanf("%d",&x);
                con(nod,x,INF);
                con(x,nod+1,INF);
            }
            nod++;
        }
        long long ans=0;
        while(bfs()){ans+=dfs(s,INF);}
        cout<<all-ans;
        return 0;
    }
  • 相关阅读:
    适用于 Laravel 的内部收单模块
    适用于 Laravel API 的签名看守器
    适用于 Laravel 的百度搜索推送
    适用于Yii2的千万级数据秒分页
    PostMan 代理的一个大坑
    PHP 各种金融利息的计算方法
    软件工程之UML建模课
    Windows 通过 cmd 得到域名的dns
    在windows下,通过git-bash里的ssh,远程登陆虚拟机里的linux
    Java常见缩写
  • 原文地址:https://www.cnblogs.com/qwerta/p/9535128.html
Copyright © 2011-2022 走看看