您的位置:首页 > 其它

BZOJ 3550 Vacation

2016-06-24 19:59 211 查看
http://www.lydsy.com/JudgeOnline/problem.php?id=3550

题意:有3N个数,你需要选出一些数,首先保证任意长度为N的区间中选出的数的个数<=K个,其次要保证选出的数的个数最大。

思路:和这题类似http://www.cnblogs.com/qzqzgfy/p/5612261.html

可以转换成不等式然后求费用流。

#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<cstring>
#define inf 0x7fffffff
int tot,go[200005],next[200005],first[200005],flow[200005],cost[200005];
int dis[200005],vis[200005],op[200005],edge[200005],from[200005],ans,a[200005];
int n,K,S,T,c[200005];
int read(){
int t=0,f=1;char ch=getchar();
while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
while ('0'<=ch&&ch<='9'){t=t*10+ch-'0';ch=getchar();}
return t*f;
}
void insert(int x,int y,int z,int l){
tot++;
go[tot]=y;
next[tot]=first[x];
first[x]=tot;
flow[tot]=z;
cost[tot]=l;
}
void add(int x,int y,int z,int l){
insert(x,y,z,l);op[tot]=tot+1;
insert(y,x,0,-l);op[tot]=tot-1;
}
bool spfa(){
for (int i=S;i<=T;i++) dis[i]=0x3f3f3f3f,vis[i]=0;
int h=1,t=1;vis[S]=1;c[1]=S;dis[S]=0;
while (h<=t){
int now=c[h++];
for (int i=first[now];i;i=next[i]){
int pur=go[i];
if (dis[pur]>dis[now]+cost[i]&&flow[i]){
dis[pur]=dis[now]+cost[i];
from[pur]=now;
edge[pur]=i;
if (vis[pur]) continue;
c[++t]=pur;
vis[pur]=1;
}
}
vis[now]=0;
}
return dis[T]!=0x3f3f3f3f;
}
void updata(){
int mn=0x7fffffff;
for (int i=T;i!=S;i=from[i]){
mn=std::min(mn,flow[edge[i]]);
}
for (int i=T;i!=S;i=from[i]){
flow[edge[i]]-=mn;
flow[op[edge[i]]]+=mn;
ans+=mn*cost[edge[i]];
}
}
void mncostflow(){
ans=0;
while (spfa()) updata();
printf("%d\n",-ans);
}
int main(){
n=read();K=read();S=0;T=2*n+3;
for (int i=1;i<=3*n;i++)
a[i]=read();
for (int i=1;i<=2*n+1;i++)
add(i+1,i,inf,0);
add(1,T,K,0);
add(S,2*n+2,K,0);
for (int i=1;i<=n;i++)
add(i+1,1,1,-a[i]);
for (int i=n+1;i<=n+n;i++)
add(i+1,i+1-n,1,-a[i]);
for (int i=n+n+1;i<=n*3;i++)
add(2*n+2,i-n+1,1,-a[i]);
mncostflow();
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: