zoukankan      html  css  js  c++  java
  • BZOJ 3438: 小M的作物( 最小割 )

    orz出题人云神...

     放上官方题解... 转成最小割然后建图跑最大流就行了...

     

    ------------------------------------------------------------------------------------------

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<iostream>
      
    #define rep(i, n) for(int i = 0; i < n; i++)
    #define clr(x, c) memset(x, c, sizeof(x))
      
    using namespace std;
     
    const int maxn = 3010, inf = int(2e9);
     
    struct edge {
    int to, cap;
    edge*next, *rev;
    } E[4008000], *pt = E, *head[maxn];
     
    inline void add(int u, int v, int w) {
    pt->to = v, pt->cap = w;
    pt->next = head[u];
    head[u] = pt++;
    }
    inline void add_edge(int u, int v, int w) {
    add(u, v, w), add(v, u, 0);
    head[u]->rev = head[v];
    head[v]->rev = head[u];
    }
     
    edge*p[maxn], *cur[maxn];
    int h[maxn], cnt[maxn], S, T, N;
     
    int maxFlow() {
    clr(h, 0), clr(cnt, 0), cnt[S] = N;
    rep(i, N) cur[i] = head[i];
    edge*e;
    int flow = 0;
    for(int x = S, A = inf; h[S] < N; ) {
    for(e = head[x]; e; e = e->next) 
       if(h[e->to] + 1 == h[x] && e->cap) break;
    if(e) {
    cur[x] = p[e->to] = e;
    A = min(A, e->cap);
    x = e->to;
    if(x == T) {
    for(; x != S; x = p[x]->rev->to) {
    p[x]->cap -= A;
    p[x]->rev->cap += A;
    }
    flow += A;
    A = inf;
    }
    } else {
    if(!--cnt[h[x]]) break;
    h[x] = N;
    for(e = head[x]; e; e = e->next) if(h[e->to] + 1 < h[x] && e->cap) {
    h[x] = h[e->to] + 1;
    cur[x] = e;
    }
    ++cnt[h[x]];
    if(x != S) x = p[x]->rev->to;
    }
    }
    return flow;
    }
     
    int main() {
    freopen("test.in", "r", stdin);
    int ans = 0, n;
    clr(head, 0);
    cin >> n;
    S = 0, T = n + 1, N = T + 1;
    rep(i, n) {
    int v;
    scanf("%d", &v);
    ans += v;
    add_edge(S, i + 1, v);
    }
    rep(i, n) {
    int v;
    scanf("%d", &v);
    ans += v;
    add_edge(i + 1, T, v);
    }
    cin >> n;
    while(n--) {
    int k, c1, c2, t;
    scanf("%d%d%d", &k, &c1, &c2);
    ans += c1 + c2;
    int u = N++, v = N++;
    add_edge(S, u, c1), add_edge(v, T, c2);
    while(k--) {
    scanf("%d", &t);
    add_edge(u, t, inf), add_edge(t, v, inf);
    }
    }
    cout << ans - maxFlow() << " ";
    return 0;
    } 

    ------------------------------------------------------------------------------------------ 

    3438: 小M的作物

    Time Limit: 10 Sec  Memory Limit: 256 MB
    Submit: 474  Solved: 226
    [Submit][Status][Discuss]

    Description


     背景

        小M还是个特么喜欢玩MC的孩纸。。。

     描述

        小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
    421
    232
    1
    23212

    Sample Output


    11

    样例解释

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

    数据范围与约定

    对于100%的数据,1<=k< n<= 1000,0

    HINT

    Source

  • 相关阅读:
    WPF-学习笔记 将控件添加到Grid中的指定行指定列
    WPF 学习笔记-在WPF下创建托盘图标
    WPF-学习笔记 动态修改控件Margin的值
    WPF-学习笔记 按下鼠标拖动窗口
    WPF 学习笔记-判断动画完成的画件
    WPF 学习笔记-跨线程引用控件
    WPF 学习笔记-设置属性使窗口不可改变大小
    C语言博客作业02循环结构
    C语言博客作业03函数
    C语言博客作业01分支、顺序结构
  • 原文地址:https://www.cnblogs.com/JSZX11556/p/4658339.html
Copyright © 2011-2022 走看看