题目:给定N个区间(ai,bi)权值wi,求最大权和且每个点最多覆盖K次。
构图:将区间端点离散化为(1,2,3.....G)
源点0 汇点G+1
addedge(i,i+1,k,0) 容量k , 费用0 ,用以限制最多覆盖K次
再处理N个区间离散化后的(ai,bi),addedge(ai,bi,1,-wi);
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;
import java.util.TreeSet;
public class Main {
public static void main(String[] args) {
new POJ3680().solve();
}
}
class POJ3680{
InputReader in = new InputReader(System.in);
PrintWriter out = new PrintWriter(System.out);
final int N = 208 ;
int[] a = new int[N] ;
int[] b = new int[N] ;
int[] w = new int[N] ;
Hash hash = new Hash() ;
MinCostMaxFlow mcmf = new MinCostMaxFlow() ;
void solve() {
int t = in.nextInt() ;
while(t-- > 0){
hash.clear() ;
int n = in.nextInt() ;
int k = in.nextInt() ;
for(int i = 1 ; i <= n ; i++){
a[i] = in.nextInt() ;
b[i] = in.nextInt() ;
w[i] = in.nextInt() ;
hash.add(a[i]) ;
hash.add(b[i]) ;
}
hash.toArray() ;
int src = 0 ;
int meet = hash.size() + 1 ;
mcmf.clear(meet) ;
for(int i = 0 ; i < meet ; i++)
mcmf.addedge(i , i+1 , k , 0) ;
for(int i = 1 ; i <= n ; i++)
mcmf.addedge(hash.getId(a[i]) , hash.getId(b[i]) , 1 , -w[i]) ;
mcmf.doMCMF(src , meet) ;
out.println(-mcmf.minCost) ;
}
out.flush() ;
}
}
class Hash{
TreeSet<Integer> tree = new TreeSet<Integer>() ;
int[] array ;
void clear(){
tree.clear() ;
}
void add(int x){
tree.add(x) ;
}
int size(){
return tree.size() ;
}
void toArray(){
array = new int[tree.size()] ;
int idx = 0 ;
for(int i : tree) array[idx++] = i ;
}
int getId(int key){
return Arrays.binarySearch(array , key) + 1 ;
}
}
class MinCostMaxFlow{
final int MAXN = 1010;
final int MAXM = 10010;
final int INF = 0x3f3f3f3f ;
class Edge{
int to,next,cap,flow,cost ;
public Edge(int to , int cap , int cost , int flow , int next) {
this.to = to ;
this.cap = cap ;
this.cost = cost ;
this.flow = flow ;
this.next = next ;
}
}
Edge[] edge = new Edge[MAXM] ;
int[] head = new int [MAXN] ;
int tol ;
int[] pre = new int[MAXN] ;
int[] dis = new int[MAXN] ;
boolean[] vis = new boolean[MAXN] ;
int N;
void clear(int n){
N = n + 2 ;
tol = 0;
Arrays.fill(head , -1) ;
}
void addedge(int u,int v,int cap,int cost){
edge[tol] = new Edge(v, cap, cost, 0, head[u]) ;
head[u] = tol++;
edge[tol] = new Edge(u, 0, -cost, 0, head[v]) ;
head[v] = tol++;
}
boolean spfa(int s,int t)
{
Queue<Integer> q = new LinkedList<Integer>() ;
for(int i = 0 ; i < N ; i++){
dis[i] = INF ;
vis[i] = false ;
pre[i] = -1 ;
}
dis[s] = 0 ;
vis[s] = true ;
q.add(s) ;
while(! q.isEmpty()){
int u = q.poll() ;
vis[u] = false ;
for(int i = head[u] ; i != -1 ; i = edge[i].next){
int v = edge[i].to ;
if(edge[i].cap > edge[i].flow && dis[v] > dis[u] + edge[i].cost){
dis[v] = dis[u] + edge[i].cost ;
pre[v] = i ;
if(! vis[v]){
vis[v] = true;
q.add(v);
}
}
}
}
if(pre[t] == -1)return false; //找不到一条增广路径
else return true;
}
int maxFlow ;
int minCost ;
void doMCMF(int s,int t){
maxFlow = 0 ;
minCost = 0 ;
while(spfa(s , t)){
int Min = INF ;
for(int i = pre[t] ; i != -1 ; i = pre[edge[i^1].to])
Min = Math.min(Min , edge[i].cap - edge[i].flow) ;
for(int i = pre[t] ; i != -1 ; i = pre[edge[i^1].to]){
edge[i].flow += Min;
edge[i^1].flow -= Min;
minCost += edge[i].cost * Min ;
}
maxFlow += Min ;
}
}
}
class InputReader {
public BufferedReader reader;
public StringTokenizer tokenizer;
public InputReader(InputStream stream) {
reader = new BufferedReader(new InputStreamReader(stream), 32768);
tokenizer = null;
}
public String next() {
while (tokenizer == null || !tokenizer.hasMoreTokens()) {
try {
tokenizer = new StringTokenizer(reader.readLine());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
return tokenizer.nextToken();
}
public int nextInt() {
return Integer.parseInt(next());
}
public long nextLong() {
return Long.parseLong(next());
}
public double nextDouble() {
return Double.parseDouble(next());
}
}