原题: http://poj.org/problem?id=3680
题意:
你想要选择一些区间并得到这些区间的cost,但是要求任意一个点都最多被K个区间覆盖,问最大cost
解析:
因为端点被覆盖的次数一定大于中间点,所以只需要考虑中间点即可。(离散化)
首先连上sp-1-2-…-n-ep的边,容量为K,花费为0。那么之后怎么跑每个点都只会被经过K次。对于区间[L,R],连一条L到R的边,容量为1,花费为-cost(因为要花费最大,而用得是最小花费板子,所以取反)。
这样到没有到达流量上限时,会优先跑-cost这条边,也就得到了在流量小于K前提下的最大花费。
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<queue>
#include<algorithm>
using namespace std;
#define LL long long
#define debug(i) printf("%d\n",i)
const int maxn=2009;
const int inf=0x3f3f3f3f;
int head[maxn],nex[maxn],to[maxn],now;
int val[maxn],cost[maxn];
void add(int a,int b,int v,int c){// 反边流量0,花费-c
to[now]=b;val[now]=v;cost[now]=c;
nex[now]=head[a];head[a]=now++;
to[now]=a;val[now]=0;cost[now]=-c;
nex[now]=head[b];head[b]=now++;
}
int sp,ep;
int dis[maxn];
bool vis[maxn];
int pre[maxn];
bool SPFA(int &flow,int &cos){
memset(vis,0,sizeof(vis));
memset(pre,-1,sizeof(pre));
memset(dis,0x3f,sizeof(dis));
queue<int>Q;
dis[sp]=0;vis[sp]=1;Q.push(sp);
int d=inf;
while(!Q.empty()){
int p=Q.front();Q.pop();
vis[p]=0;
for(int i=head[p];~i;i=nex[i]){
int u=to[i];
if(val[i]>0&&dis[u]-cost[i]>dis[p]){
dis[u]=dis[p]+cost[i];
pre[u]=i;
if(!vis[u]){
vis[u]=1;
Q.push(u);
}
}
}
}
if(dis[ep]==inf)return 0;
for(int i=pre[ep];~i;i=pre[to[i^1]]){
d=min(d,val[i]);
}
for(int i=pre[ep];~i;i=pre[to[i^1]]){
val[i]-=d;
val[i^1]+=d;
cos+=cost[i]*d;
}
flow+=d;
return 1;
}
int MinCost(){
int flow=0,cost=0;
while(SPFA(flow,cost));
return cost;
}
void init(){
now=0;
memset(head,-1,sizeof(head));
}
int a[maxn],b[maxn],tmp[maxn];
int c[maxn];
int main(){
int t;scanf("%d",&t);
while(t--){
init();
int n;int k;scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++){
scanf("%d%d%d",&a[i],&b[i],c+i);
tmp[i*2-1]=a[i];
tmp[i*2]=b[i];
}
sort(tmp+1,tmp+1+2*n);
int num=unique(tmp+1,tmp+1+2*n)-tmp-1;
for(int i=1;i<=n;i++){
a[i]=lower_bound(tmp+1,tmp+1+num,a[i])-tmp;
b[i]=lower_bound(tmp+1,tmp+1+num,b[i])-tmp;
}
sp=0,ep=num+1;
add(sp,1,k,0);
add(num,ep,k,0);
for(int i=1;i<num;i++){
add(i,i+1,k,0);
}
for(int i=1;i<=n;i++){
add(a[i],b[i],1,-c[i]);
}
int ans=-MinCost();
printf("%d\n",ans);
}
}