zoukankan      html  css  js  c++  java
  • BZOJ_3438_小M的作物_最小割

    BZOJ_3438_小M的作物_最小割

    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。
     

    求最大收益,可以转化成总收益减去最小损失,也就是说我们要求一个最小割。
    设S为A号耕地,T为B号耕地。
    对于每个作物,单独种时不能两块都种,于是分别向S。T连边表示损失。
    对于每个组合,新开两个点,这两个点向S,T连边,组合里的点向这两个点连边,表示损失时组合里的点一起损失。
    求最小割即可。
     
    代码:
    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    using namespace std;
    #define N 4050
    #define S (4000)
    #define T (4001)
    #define inf 2000000000
    #define M 4000050
    int head[N],to[M],nxt[M],flow[M],cnt=1,n,m,sum;
    int dep[N],Q[N],l,r;
    inline void add(int u,int v,int f) {
        to[++cnt]=v; nxt[cnt]=head[u]; head[u]=cnt; flow[cnt]=f;
        to[++cnt]=u; nxt[cnt]=head[v]; head[v]=cnt; flow[cnt]=0;
    }
    bool bfs() {
        memset(dep,0,sizeof(dep));
        l=r=0;
        Q[r++]=S; dep[S]=1;
        while(l<r) {
            int x=Q[l++],i;
            for(i=head[x];i;i=nxt[i]) if(!dep[to[i]]&&flow[i]) {
                dep[to[i]]=dep[x]+1; if(to[i]==T) return 1; Q[r++]=to[i];
            }
        }
        return 0;
    }
    int dfs(int x,int mf) {
        if(x==T) return mf;
        int nf=0,i;
        for(i=head[x];i;i=nxt[i]) if(dep[to[i]]==dep[x]+1&&flow[i]) {
            int tmp=dfs(to[i],min(mf-nf,flow[i]));
            nf+=tmp; flow[i]-=tmp; flow[i^1]+=tmp;
            if(nf==mf) break;
        }
        dep[x]=0;
        return nf;
    }
    void dinic() {
        int f;
        while(bfs()) while(f=dfs(S,inf)) sum-=f;
        printf("%d
    ",sum);
    }
    int main() {
        scanf("%d",&n);
        int tot=n;
        int i,x,y,z,g,h;
        for(i=1;i<=n;i++) {
            scanf("%d",&x);
            sum+=x;
            add(S,i,x);
        }
        for(i=1;i<=n;i++) {
            scanf("%d",&x);
            sum+=x;
            add(i,T,x);
        }
        scanf("%d",&m);
        while(m--) {
            scanf("%d%d%d",&x,&y,&z);
            sum+=y; sum+=z;
            add(S,++tot,y); add(++tot,T,z);
            for(i=1;i<=x;i++) {
                scanf("%d",&h);
                add(tot-1,h,inf);
                add(h,tot,inf);
            }
        }
        dinic();
    }
    
  • 相关阅读:
    优化-IO
    优化-cpu
    优化-内存
    系统优化
    snort -- 入侵检测系统
    tripwire--入侵检测系统
    sudo
    selinux
    pptpd
    C++ 内联函数
  • 原文地址:https://www.cnblogs.com/suika/p/8823258.html
Copyright © 2011-2022 走看看