题目链接:http://www.lydsy.com:808/JudgeOnline/problem.php?id=3550
题意:给出3×n个数字,从中选出一些数字,要求每连续的n个数字中选出的数字个数不超过K。使得选出的数字之和最大。
思路:跟这个差不多
http://www.cnblogs.com/jianglangcaijin/p/3799759.html
流量平衡方程:a[i]表示i选不选,b[i]表示第i个等式的辅助变量
0=0
a[1]+a[2]+……a[n]+b[1]=k
a[2]+a[3]+……a[n+1]+b[2]=k
…………
a[2*n+1]+a[2*n+2]+……+a[3*n]+b[2*n+1]=k
0=0
相减之后是:
a[1]+a[2]+……a[n]+b[1]=k
a[n+1]-a[1]+b[2]-b[1]=0
a[n+2]-a[2]+b[3]-b[2]=0
…………
-a[2*n+1]-a[2*n+2]-………-a[3*n]-b[2*n+1]=-k
struct node { int u,v,flow,cost,next; }; node edges[N*100]; int head[N],e; void add(int u,int v,int flow,int cost) { edges[e].u=u; edges[e].v=v; edges[e].cost=cost; edges[e].flow=flow; edges[e].next=head[u]; head[u]=e++; } void Add(int u,int v,int flow,int cost) { add(u,v,flow,cost); add(v,u,0,-cost); } int C[N],F[N],pre[N]; int visit[N]; int SPFA(int s,int t) { clr(pre,-1); queue<int> Q; Q.push(s); int i; for(i=0;i<=t;i++) C[i]=INF,F[i]=0,visit[i]=0; int u,v,c,f; C[s]=0; F[s]=INF; while(!Q.empty()) { u=Q.front(); Q.pop(); visit[u]=0; for(i=head[u];i!=-1;i=edges[i].next) { v=edges[i].v; c=edges[i].cost; f=edges[i].flow; if(f>0&&C[v]>C[u]+c) { C[v]=C[u]+c; F[v]=min(F[u],f); pre[v]=i; if(!visit[v]) { Q.push(v); visit[v]=1; } } } } return F[t]; } int MCMF(int s,int t) { int ans=0,i,temp,x; while(temp=SPFA(s,t)) { for(i=t;i!=s;i=edges[pre[i]].u) { x=pre[i]; ans+=temp*edges[x].cost; edges[x].flow-=temp; edges[x^1].flow+=temp; } } return ans; } int n,K; int a[N]; int main() { n=getInt(); K=getInt(); clr(head,-1); int s=0,t=3*n+1; int i; for(i=1;i<=n*3;i++) a[i]=getInt(); Add(s,1,K,0); Add(2*n+2,t,K,0); for(i=1;i<=n;i++) Add(1,i+1,1,-a[i]); for(i=n+1;i<=2*n;i++) Add(i-n+1,i+1,1,-a[i]); for(i=2*n+1;i<=3*n;i++) Add(i-n+1,2*n+2,1,-a[i]); for(i=1;i<=2*n+1;i++) Add(i,i+1,INF,0); int ans=MCMF(s,t); printf("%d\n",-ans); }