BZOJ3438 小M的作物

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3438

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

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

Orz Greens

Orz KPM

放官方题解跑

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <algorithm>
 4 #include <cstring>
 5 #include <queue>
 6 #define rep(i,l,r) for(int i=l; i<=r; i++)
 7 #define clr(x,y) memset(x,y,sizeof(x))
 8 #define travel(x) for(Edge *p=last[x]; p; p=p->pre)
 9 using namespace std;
10 const int INF = 0x7fffffff;
11 const int maxn = 3010;
12 inline int read(){
13     int ans = 0, f = 1;
14     char c = getchar();
15     for(; !isdigit(c); c = getchar())
16     if (c == '-') f = -1;
17     for(; isdigit(c); c = getchar())
18     ans = ans * 10 + c - '0';
19     return ans * f;
20 }
21 struct Edge{
22     Edge *pre,*rev; int to,cost;
23 }edge[4010000],*last[maxn],*cur[maxn],*pt = edge;
24 int n,m,x,y,z,k,c1,c2,cnt,ans=0,d[maxn];
25 queue <int> q;
26 inline void addedge(int x,int y,int z){
27     pt->pre = last[x]; pt->to = y; pt->cost = z; last[x] = pt++;
28 }
29 inline void add(int x,int y,int z){
30     addedge(x,y,z); addedge(y,x,0); last[x]->rev = last[y]; last[y]->rev = last[x];
31 }
32 bool bfs(){
33     while (!q.empty()) q.pop();
34     clr(d,-1); d[0] = 0; q.push(0);
35     while (!q.empty()){
36         int now = q.front(); q.pop();
37         travel(now){
38             if (d[p->to] == -1 && p->cost > 0){
39                 d[p->to] = d[now] + 1;
40                 q.push(p->to);
41                 if (p->to == n + 1) return 1;
42             }
43         }
44     }
45     return 0;
46 }
47 int dfs(int x,int flow){
48     if (x == n + 1 || (!flow)) return flow; int w = 0;
49     for (Edge *p = cur[x]; p && w < flow; p = p->pre){
50         if (d[p->to] == d[x] + 1 && p->cost > 0){
51             int delta = dfs(p->to,min(flow-w,p->cost));
52             p->cost -= delta; p->rev->cost += delta; w += delta;
53             if (p->cost) cur[x] = p;
54         }
55     }
56     if (w < flow) d[x] = -1;
57     return w;
58 }
59 int main(){
60     n = read(); clr(last,0); cnt = n + 2;
61     rep(i,1,n) x = read(), ans += x, add(0,i,x);
62     rep(i,1,n) x = read(), ans += x, add(i,n+1,x);
63     m = read();
64     rep(i,1,m){
65         k = read(); c1 = read(); c2 = read();
66         ans += c1 + c2;
67         int u = cnt++, v = cnt++;
68         add(0,u,c1); add(v,n+1,c2);
69         rep(j,1,k){
70             x = read();
71             add(u,x,INF); add(x,v,INF);
72         }
73     }
74     int mxflow = 0;
75     while (bfs()){
76         rep(i,0,cnt-1) cur[i] = last[i];
77         mxflow += dfs(0,INF);
78     }
79     printf("%d
",ans-mxflow);
80     return 0;
81 }
View Code
原文地址:https://www.cnblogs.com/jimzeng/p/bzoj3438.html