BZOJ3438:小M的作物 (最大闭合权图->最小割)
小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。
思路:orzpopoqqq。假定全部在A里,然后去找增广流。 如果很好地理解了用最大流求最大闭合权图的话,就不难想通。
最大闭合权图:原点与代价点连接,收益点与汇点连接; 收益和-最大流=最大净收益。 那么现在的基本代价或者收益是ai-bi,。然后破坏集合的代价是c1i,得到集合的收益是c2i。 差不多就酱紫。具体的请去看popoqqq的题解。
和BZOJ3894差不多,就不多说了:http://www.cnblogs.com/hua-dong/p/8655375.html
#include<cstdio> #include<cstdlib> #include<iostream> #include<algorithm> using namespace std; const int maxn=4000010; const long long inf=100000000000000; int N,M,S,T,cnt=1; long long ans,maxflow,cap[maxn]; int Laxt[maxn],To[maxn],Next[maxn],vd[maxn],dis[maxn]; void add(int u,int v,long long c) { Next[++cnt]=Laxt[u]; Laxt[u]=cnt; To[cnt]=v; cap[cnt]=c; } long long sap(int u,long long flow) { if(flow==0||u==T) return flow; long long tmp,delta=0; for(int i=Laxt[u];i;i=Next[i]){ if(dis[u]==dis[To[i]]+1&&cap[i]>0){ tmp=sap(To[i],min(cap[i],flow-delta)); delta+=tmp; cap[i]-=tmp; cap[i^1]+=tmp; if(delta==flow||dis[S]>T+1) return delta; } } vd[dis[u]]--; if(vd[dis[u]]==0) dis[S]=T+2; vd[++dis[u]]++; return delta; } int main() { int i,j,x,y,num; scanf("%d",&N); S=0; T=3100; for(i=1;i<=N;i++){ scanf("%d",&x); ans+=x; add(S,i,x); add(i,S,0); } for(i=1;i<=N;i++){ scanf("%d",&x); ans+=x; add(i,T,x); add(T,i,0); } scanf("%d",&M); for(i=1;i<=M;i++){ scanf("%d",&num); scanf("%d%d",&x,&y); ans+=x+y; add(S,N+i,x); add(N+i,S,0); add(N+M+i,T,y); add(T,N+M+i,0); for(j=1;j<=num;j++){ scanf("%d",&x); add(N+i,x,inf); add(x,N+i,0); add(x,N+M+i,inf); add(N+M+i,x,0); } } while(dis[S]<=T) maxflow+=sap(S,inf); printf("%d\n",ans-maxflow); return 0; }
It is your time to fight!