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

      

    题目描述

    小M在MC里开辟了两块巨大的耕地A和B(你可以认为容量是无穷),现在,小P有n中作物的种子,每种作物的种子有1个(就是可以种一棵作物)(用1...n编号)。

    现在,第i种作物种植在A中种植可以获得ai的收益,在B中种植可以获得bi的收益,而且,现在还有这么一种神奇的现象,就是某些作物共同种在一块耕地中可以获得额外的收益,小M找到了规则中共有m种作物组合,第i个组合中的作物共同种在A中可以获得c1i的额外收益,共同总在B中可以获得c2i的额外收益。

    小M很快的算出了种植的最大收益,但是他想要考考你,你能回答他这个问题么?

    输入输出格式

    输入格式:

    第一行包括一个整数n

    第二行包括n个整数,表示ai第三行包括n个整数,表示bi第四行包括一个整数m接下来m行,

    对于接下来的第i行:第一个整数ki,表示第i个作物组合中共有ki种作物,

    接下来两个整数c1i,c2i,接下来ki个整数,表示该组合中的作物编号。

    输出格式:

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

    输入输出样例

    输入样例#1: 复制
    3
    4 2 1
    2 3 2
    1
    2 3 2 1 2
    输出样例#1: 复制
    11

    说明

    样例解释

    A耕地种1,2,B耕地种3,收益4+2+3+2=11。

    数据范围与约定

    1<=k< n<= 1000,0 < m < = 1000 保证所有数据及结果不超过2*10^9。

    非常好的网络流题  和善意的谎言有一点类似

    这种二选一的一般将两种选择转化为源点 和 汇点  然后求一下最小割就肯定是二选一了

    比较难处理的是组合优惠

    可以如下建图:

    黄边c1 c2  蓝边为inf(不可减)  就完美的解决了

    #include<bits/stdc++.h>
    using namespace std;
    //input by bxd
    #define rep(i,a,b) for(int i=(a);i<=(b);i++)
    #define repp(i,a,b) for(int i=(a);i>=(b);--i)
    #define RI(n) scanf("%d",&(n))
    #define RII(n,m) scanf("%d%d",&n,&m)
    #define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k)
    #define RS(s) scanf("%s",s);
    #define ll long long
    #define pb push_back
    #define REP(i,N)  for(int i=0;i<(N);i++)
    #define CLR(A,v)  memset(A,v,sizeof A)
    //////////////////////////////////
    #define inf 0x3f3f3f3f
    const int N=4e5+44;
    const int M=4e6+54;
    
    struct edge {
        int to, next, w;
    } e[M << 1];
    int head[N], cnt = 1;
    void add(int x, int y, int z) {
        e[++cnt] = (edge){y, head[x], z};
        head[x] = cnt;
        e[++cnt] = (edge){x, head[y], 0};
        head[y] = cnt;
    }
    int level[N];
    bool bfs(int s, int t) {
        memset(level, 0, sizeof level);
        queue<int> q;
        level[s] = 1;
        q.push(s);
        while (!q.empty()) {
            int pos = q.front();
            q.pop();
            for (int i = head[pos]; i; i = e[i].next) {
                int nx = e[i].to;
                if (!e[i].w || level[nx]) continue;
                level[nx] = level[pos] + 1;
                q.push(nx);
            }
        }
        return level[t];
    }
    int dfs(int s, int t, int flow) {
        if (s == t) return flow;
        int ret = 0;
        for (int i = head[s]; flow && i; i = e[i].next) {
            int nx = e[i].to;
            if (level[nx] == level[s] + 1 && e[i].w) {
                int tmp = dfs(nx, t, min(flow, e[i].w));
                e[i].w -= tmp;
                e[i ^ 1].w += tmp;
                flow -= tmp;
                ret += tmp;
            }
        }
        if (!ret) level[s] = 0;
        return ret;
    }
    int dinic(int s, int t) {
        int ret = 0;
        while (bfs(s, t)) ret += dfs(s, t, inf);
        return ret;
    }
    int n,m,s,t,T,a,b,c1,x,k,c2,sum;
    
    int main()
    {
        RI(n);
        s=0,t=n+1;
        rep(i,1,n){RI(x);add(s,i,x);sum+=x;}
        rep(i,1,n){RI(x);add(i,t,x);sum+=x;}
        RI(m);
        rep(i,1,m)
        {
            RIII(k,c1,c2);
            add(s,i+n+1,c1);add(i+m+n+2,t,c2);sum+=c1,sum+=c2;
            rep(j,1,k)
            {
                RI(x);add(i+n+1,x,inf);add(x,i+m+n+2,inf);
            }
        }
        cout<<sum-dinic(s,t);
    
        return 0;
    }
    View Code
  • 相关阅读:
    servlet的配置
    getRequestDispatcher()与sendRedirect()的区别
    request.setAttribute()怎么用的?
    <jsp:useBean>元素使用全解
    jsp中使用javabean简单例子
    2-1
    跟我想的一样,已经连续暴跌三天了。
    我的判断很正确
    我靠算个账发现最近打德扑输了好多钱啊,怀疑PokerStars里是不是有好多机器人作弊骗钱呢???
    1-18
  • 原文地址:https://www.cnblogs.com/bxd123/p/10954125.html
Copyright © 2011-2022 走看看