bzoj3438: 小M的作物
3438: 小M的作物
Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 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
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。
样例解释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 }