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\n",ans-mxflow); 80 return 0; 81 }