有多个区间,每个区间都是开区间,每一个区间都有一个权值,现在要保证每一个点不被覆盖k次以上,并且要是所有区间权值和最大
将端点离散化
添加源汇
汇点与数轴上最后一个点连 容量为k,费用0
源点与数轴上第一个点连,容量为k,费用为0
这两条弧用来保证一个点不被重复覆盖k次 ( 其实我们每一次增广网络的时候相当于从起点到终点画一条线,每次选中尽量多的不重叠的区间,这样最多重复画k次那么就一定不会有点被覆盖k次以上)
然后相邻的点 i 和 i+1 连一条边 容量 INF , 费用0
然后区间(a,b)
相应点连边,容量为 1 费用为 -w
最后跑一边最小费用即可
答案取反。
此题建图很经典
Time Limit: 5000MS | Memory Limit: 65536K | |
Total Submissions: 6241 | Accepted: 2537 |
Description
You are given N weighted open intervals. The ith interval covers (ai, bi) and weighs wi. Your task is to pick some of the intervals to maximize the total weights under the limit that no point in the real axis is covered more than k times.
Input
The first line of input is the number of test case.
The first line of each test case contains two integers, N and K (1 ≤ K ≤ N ≤ 200).
The next N line each contain three integers ai, bi, wi(1 ≤ ai < bi ≤ 100,000, 1 ≤ wi ≤ 100,000) describing the intervals.
There is a blank line before each test case.
Output
For each test case output the maximum total weights in a separate line.
Sample Input
4 3 1 1 2 2 2 3 4 3 4 8 3 1 1 3 2 2 3 4 3 4 8 3 1 1 100000 100000 1 2 3 100 200 300 3 2 1 100000 100000 1 150 301 100 200 300
Sample Output
14 12 100000 100301
Source
#include<iostream>
#include<cstring>
#include<cstdio>
#include<string>
#include<algorithm>
#include<queue>
using namespace std;
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
#define MAXN 1000
#define MAXM 100000
#define INF 0xFFFFFF
struct edge
{
int to,c,w,next;
};
edge e[MAXM];
bool in[MAXN];
int head[MAXN],dis[MAXN],pre[MAXN],en,maxflow,mincost;
int vn,st,ed;
int n,k;
void add(int a,int b,int c,int d)
{
e[en].to=b;
e[en].c=c;
e[en].w=d;
e[en].next=head[a];
head[a]=en++;
e[en].to=a;
e[en].c=0;
e[en].w=-d;
e[en].next=head[b];
head[b]=en++;
}
bool spfa(int s)
{
queue<int> q;
for(int i=0;i<=vn;i++)
{
dis[i]=INF;
in[i]=false;
pre[i]=-1;
}
dis[s]=0;
in[s]=true;
q.push(s);
while(!q.empty())
{
int tag=q.front();
in[tag]=false;
q.pop();
for(int i=head[tag];i!=-1;i=e[i].next)
{
int j=e[i].to;
if(e[i].w+dis[tag]<dis[j] && e[i].c)
{
dis[j]=e[i].w+dis[tag];
pre[j]=i;
if(!in[j])
{
q.push(j);
in[j]=true;
}
}
}
}
if(dis[ed]==INF)
return false;
return true;
}
void update()
{
int flow=INF;
for (int i=pre[ed];i!=-1;i=pre[e[i^1].to])
if(e[i].c<flow) flow=e[i].c;
for (int i=pre[ed];i!=-1;i=pre[e[i^1].to])
{
e[i].c-=flow,e[i^1].c+=flow;
}
maxflow+=flow;
mincost+=flow*dis[ed];
}
void mincostmaxflow()
{
maxflow=0,mincost=0;
while(spfa(st)){
update();
}
}
int hash[600];
int p;
int l[600],r[600],w[600];
int getHash(int x){
int l=0,r=p;
while(l<=r){
int m=(l+r)/2;
if(hash[m]==x)
return m;
else if(hash[m]>x)
r=m-1;
else if(hash[m]<x)
l=m+1;
}
return -1;
}
int main(){
int t;
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&k);
p=0;
//离散化
for(int i=0;i<n;i++){
scanf("%d%d%d",&l[i],&r[i],&w[i]);
hash[p++]=l[i];
hash[p++]=r[i];
}
sort(hash,hash+p);
p=unique(hash,hash+p)-hash;
//建图
memset(head,-1,sizeof(head));en=0;
st=0,ed=p+1,vn=ed+1;
add(st,1,k,0);
add(p,ed,k,0);
for(int i=1;i<p;i++)
add(i,i+1,INF,0);
for(int i=0;i<n;i++)
{
int ll=getHash(l[i]);
int rr=getHash(r[i]);
add(ll+1,rr+1,1,-w[i]);
}
mincostmaxflow();
printf("%d\n",-mincost);
}
return 0;
}