Time Limit: 5000MS | Memory Limit: 65536K | |
Total Submissions: 8363 | Accepted: 3569 |
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
题意:给出n个区间及其权值,从中选出一些区间使它们的权值合最大,任意一个点最多可以被覆盖k次
解题思路:先将所有点离散化一下,把区间所有的端点从小到大编号构图:
1.连接第i和i + 1个端点,容量设置为k,权值为0
2.连接第一个端点和源点,连接最后的端点和汇点,容量为k,权值为0(这样可以使每个点覆盖不超过k次)
3.连接所有区间端点(左边的连向右边的),容量为1,权值为该区间的权值*( - 1)(一个区间只能使用一次)
跑一遍最小费用流得出答案
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <vector>
#include <bitset>
using namespace std;
#define LL long long
const int INF = 0x3f3f3f3f;
int vis[405],d[405],pre[405],a[405];
struct Edge
{
int u, v, c, cost, next;
} edge[200009];
int s[405], cnt;
void init()
{
cnt = 0;
memset(s, -1, sizeof(s));
}
void add(int u, int v, int c, int cost)
{
edge[cnt].u = u;
edge[cnt].v = v;
edge[cnt].cost = cost;
edge[cnt].c = c;
edge[cnt].next = s[u];
s[u] = cnt++;
edge[cnt].u = v;
edge[cnt].v = u;
edge[cnt].cost = -cost;
edge[cnt].c = 0;
edge[cnt].next = s[v];
s[v] = cnt++;
}
bool spfa(int ss, int ee,int &flow,int &cost)
{
queue<int> q;
memset(d, INF, sizeof d);
memset(vis, 0, sizeof vis);
d[ss] = 0, vis[ss] = 1, pre[ss] = 0, a[ss] = INF;
q.push(ss);
while (!q.empty())
{
int u = q.front();q.pop();
vis[u] = 0;
for (int i = s[u]; ~i; i = edge[i].next)
{
int v = edge[i].v;
if (edge[i].c>0&& d[v]>d[u] + edge[i].cost)
{
d[v] = d[u] + edge[i].cost;
pre[v] = i;
a[v] = min(a[u], edge[i].c);
if (!vis[v])
{
vis[v] = 1;
q.push(v);
}
}
}
}
if (d[ee] == INF) return 0;
flow += a[ee];
cost += d[ee]*a[ee];
int u = ee;
while (u != ss)
{
edge[pre[u]].c -= a[ee];
edge[pre[u] ^ 1].c += a[ee];
u = edge[pre[u]].u;
}
return 1;
}
int MCMF(int ss, int ee)
{
int cost = 0, flow=0;
while (spfa(ss, ee, flow, cost));
return cost;
}
int l[205],r[205],val[205],x[405];
int main()
{
int n,k,t;
scanf("%d",&t);
while (t--)
{
scanf("%d%d", &n, &k);
init();
for(int i=1;i<=n;i++)
{
scanf("%d%d%d",&l[i],&r[i],&val[i]);
x[i*2-1]=l[i],x[2*i]=r[i];
}
sort(x+1,x+2*n+1);
int m=unique(x+1,x+1+2*n)-x;
int s = 0, e = m ;
for (int i = 1; i < m-1; i++) add(i, i+1, k, 0);
add(s,1,k,0);add(m-1,e,k,0);
for(int i=1;i<=n;i++)
{
int ll=lower_bound(x+1,x+m,l[i])-x;
int rr=lower_bound(x+1,x+m,r[i])-x;
add(ll,rr,1,-val[i]);
}
printf("%d\n", -MCMF(s, e));
}
return 0;
}