bzoj3438: 小M的作物

3438: 小M的作物

Time Limit: 10 Sec  Memory Limit: 256 MB
Submit: 868  Solved: 384
[Submit][Status][Discuss]

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。

 

一开始不会写滚去看题解的TAT

那时候完全不知道最小割是啥...

转自 http://www.cnblogs.com/rausen/p/4133449.html (其实原来是Po大爷的?

首先建立源点汇点S、T表示种在a,b两片土里,流量为收益。

然后每次读到一个集合的时候,新建两个虚拟节点si、ti,表示都种在a,b里的收益

S向si连边,ti向T连边,流量为收益,然后si、ti向集合内所有点连边。

之后跑一边最大流,ans = 总收益 - 最小割

 1 #include<bits/stdc++.h>
 2 #define N 5000
 3 #define inf 2147483647
 4 #define rep(i,l,r) for(int i=l;i<=r;i++)
 5 using namespace std;
 6 struct node{
 7     int to,next,w;
 8 }e[5000000];
 9 int head[N],a[N],b[N],c1,c2,m,n,k,x,ans,dis[N],T,tot=1,cnt;
10 inline void ins(int u,int v,int w) {
11      e[++tot].to=v; e[tot].next=head[u]; head[u]=tot; e[tot].w=w;
12 }
13 inline void insert(int u,int v,int w) {
14      ins(u,v,w); ins(v,u,0);
15 }
16 inline bool bfs(){
17      memset(dis,-1,sizeof(dis)); queue<int>q; q.push(0); dis[0]=0;
18      while(!q.empty()) {
19           int x=q.front(); q.pop();
20           for(int k=head[x];k;k=e[k].next) 
21              if(dis[e[k].to]<0 && e[k].w>0) {
22                    dis[e[k].to]=dis[x]+1; q.push(e[k].to);
23              }
24      }
25      if(dis[T]>0) return 1;else return 0;
26 }
27 int find(int x,int low){
28      if(x==T) return low;
29      int delta=low,now;
30      for(int k=head[x];k;k=e[k].next) 
31        if(e[k].w>0 && dis[e[k].to]==dis[x]+1){ 
32            now=find(e[k].to,min(e[k].w,delta));
33            e[k].w-=now; e[k^1].w+=now;   delta-=now;
34            if(!delta) return low;
35         } 
36      dis[x]=-1;
37      return low-delta;
38 }
39 int main () {
40      scanf("%d",&n); T=4100;
41      rep(i,1,n) scanf("%d",&a[i]),insert(0,i,a[i]),ans+=a[i]; rep(i,1,n) scanf("%d",&b[i]),ans+=b[i];
42      scanf("%d",&m); rep(i,1,n) insert(i,T,b[i]);  cnt=n;
43      rep(i,1,m) {
44           scanf("%d%d%d",&k,&c1,&c2); ans+=c1+c2;
45           insert(0,++cnt,c1); insert(++cnt,T,c2);  
46          rep(i,1,k) scanf("%d",&x),insert(cnt-1,x,inf),insert(x,cnt,inf);
47      }
48      while(bfs()) ans-=find(0,inf);
49      printf("%d",ans);
50 }
View Code

 

posted @ 2016-09-19 19:35  Bloodline  阅读(243)  评论(0编辑  收藏  举报