3438: 小M的作物
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。
最小割,难点在于怎么判断n个人同选的收益,只要新建两个额外点,一个向s连流量c1,一个向t连流量c2,这两个点与集合的所有点连,流量为无穷大,所以就变成了,这个集合要么都选,要么都不选,代价就是断几条边。。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<iostream> 2 #include<cstdlib> 3 #include<cmath> 4 #include<cstring> 5 #include<cstdio> 6 #include<algorithm> 7 #include<string> 8 #include<map> 9 #include<queue> 10 #include<vector> 11 #include<set> 12 #define inf 1000000000 13 #define maxn 100000+5 14 #define maxm 5000000+5 15 #define eps 1e-10 16 #define ll long long 17 #define for0(i,n) for(int i=0;i<=(n);i++) 18 #define for1(i,n) for(int i=1;i<=(n);i++) 19 #define for2(i,x,y) for(int i=(x);i<=(y);i++) 20 #define for3(i,x,y) for(int i=(x);i>=(y);i--) 21 #define for4(i,x) for(int i=head[x],y=e[i].go;i;i=e[i].next,y=e[i].go) 22 using namespace std; 23 int read(){ 24 int x=0,f=1;char ch=getchar(); 25 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 26 while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();} 27 return x*f; 28 } 29 int n,m,s,t,maxflow,tot=1,cnt,head[maxn],cur[maxn],h[maxn],q[maxn]; 30 struct edge{ 31 int go,next,w; 32 }e[maxm]; 33 void insert(int u,int v,int w){ 34 e[++tot]=(edge){v,head[u],w};head[u]=tot; 35 e[++tot]=(edge){u,head[v],0};head[v]=tot; 36 } 37 void ins(int u,int v,int w){ 38 e[++tot]=(edge){v,head[u],w};head[u]=tot; 39 e[++tot]=(edge){u,head[v],w};head[v]=tot; 40 } 41 bool bfs(){ 42 for0(i,t)h[i]=-1; 43 h[s]=0;q[1]=s;int l=0,r=1; 44 while(l!=r){ 45 int x=q[++l]; 46 for4(i,x) 47 if(e[i].w&&h[y]==-1) 48 h[y]=h[x]+1,q[++r]=y; 49 } 50 return h[t]!=-1; 51 } 52 int dfs(int x,int f){ 53 if(x==t)return f; 54 int tmp=0,used=0; 55 for4(i,x) 56 if(e[i].w&&h[y]==h[x]+1){ 57 tmp=dfs(y,min(e[i].w,f-used)); 58 e[i].w-=tmp;if(e[i].w)cur[x]=i; 59 e[i^1].w+=tmp;used+=tmp; 60 if(used==f)return f; 61 } 62 if(!used)h[x]=-1; 63 return used; 64 } 65 void dinic(){ 66 maxflow=0; 67 while(bfs()){ 68 for0(i,t)cur[i]=head[i]; 69 maxflow+=dfs(s,inf); 70 } 71 } 72 int main(){ 73 //freopen("input.txt","r",stdin); 74 //freopen("output.txt","w",stdout); 75 n=read();s=3005;t=s+1;int ans=0; 76 for1(i,n){ 77 int x=read();ans+=x; 78 insert(s,i,x); 79 } 80 for1(i,n){ 81 int x=read();ans+=x; 82 insert(i,t,x); 83 } 84 m=read(); 85 for1(i,m){ 86 int k=read(),c1=read(),c2=read();ans+=c1+c2; 87 insert(s,n+i,c1);insert(n*2+i,t,c2); 88 for1(j,k){ 89 int x=read(); 90 insert(n+i,x,inf);insert(x,n*2+i,inf); 91 } 92 } 93 dinic(); 94 printf("%d\n",ans-maxflow); 95 return 0; 96 }