题目: LINK
给定 N 个带权的开区间,第 i 个区间覆盖(ai, bi),权为 wi。现在要你挑出一些区间使得总权值最大,并且满足实轴上任意一个点被覆盖不超过 K 次。(1 <= K <= N <= 200, 1 <= ai < bi <= 100,000, 1 <= wi <= 100,000)
首先要将每个区间的端点离散化,1..M,另加源 s=0,汇 t=M+1;对每个点 i (0 <= i <= M)加边(i, i+1, K, 0);
对每个区间(ai, bi)加边(ai’, bi’, 1, -wi),其中ai’, bi’分别表示 ai, bi 离散化后对应的数值
按照这个图求最小费用最大流,得到的最小费用的相反数就是要求的结果.
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
#include <cmath>
#include <queue>
#include <map>
#include <set>
using namespace std;
#define INF 1000000000
//typedef __int64 LL;
#define N 444
int t, n, k , tot, hh[N], dis[N], inq[N], S, T, pre[N];
set<int> se;
map<int, int> ma;
struct node {
int u, v, w, c, next;
}edge[1000000];
struct no {
int u, v, w;
}ee[N];
void init() {
memset(hh, -1, sizeof(hh));
tot = 0;
}
void add(int u, int v, int w, int c) {
edge[tot].u = u; edge[tot].v = v;
edge[tot].w = w; edge[tot].c = c;
edge[tot].next = hh[u]; hh[u] = tot ++;
}
int spfa() {
queue<int > Q;
memset(pre, -1, sizeof(pre));
memset(inq, 0, sizeof(inq));
for(int i = 0; i <= T; i++) dis[i] = INF; // ?
dis[S] = 0; inq[S] = 1;
Q.push(S);
while(!Q.empty()) {
int u = Q.front(); Q.pop();
inq[u] = 0;
for(int i = hh[u]; i != -1; i = edge[i].next) {
int v = edge[i].v;
if(edge[i].w && dis[v] > dis[u] + edge[i].c){
pre[v] = i; dis[v] = dis[u] + edge[i].c;
if(!inq[v]) {
inq[v] = 1; Q.push(v);
}
}
}
}
return dis[T] != INF;
}
int mcml() {
int flow, cost;
flow = cost = 0;
while(spfa()) {
int tmp = INF;
for(int i = pre[T]; i != -1; i = pre[edge[i].u])
tmp = min(tmp, edge[i].w);
flow += tmp;
cost += dis[T] * tmp;
for(int i = pre[T]; i != -1; i = pre[edge[i].u] )
edge[i].w -= tmp, edge[i^1].w += tmp;
}
return cost;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
#endif // ONLINE_JUDGE
scanf("%d", &t);
while(t -- ) {
scanf("%d%d", &n, &k);
init();
se.clear();
ma.clear();
for(int i = 1; i <= n; i++) {
scanf("%d%d%d", &ee[i].u, &ee[i].v, &ee[i].w);
se.insert(ee[i].u); se.insert(ee[i].v);
}
int id = 1;
for(set<int >::iterator it = se.begin(); it != se.end(); it ++) {
ma[*it] = id++;
}
// build map
S = 0; T = id;
for(int i = 0; i < T; i++) {
add(i, i+1, k, 0); add(i+1, i, 0, 0);
}
for(int i = 1; i <= n; i++) {
int id1= ma[ee[i].u];
int id2 = ma[ee[i].v];
add(id1, id2, 1, -ee[i].w); add(id2, id1, 0, ee[i].w);
}
// finish build.
int ans = mcml();
printf("%d\n", -ans);
}
return 0;
}