POJ3680最小费用最大流

来源:互联网 发布:网络院线 英文 编辑:程序博客网 时间:2024/05/02 04:57

题目:给定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());}}


0 0