poj 3680 Intervals(费用流)
http://poj.org/problem?id=3680
巧妙的构图。
题目:给定N个区间(ai,bi)权值wi,求最大权和且每个点最多覆盖K次。
构图:将区间端点离散化,将第i个点连第i+1个点花费为0,容量为INF,即addedge(i,i+1,0,INF)(可用来跳过一些区间);
再处理N个区间(ai,bi),addedge(ai,bi,-wi,1);
最后源点连第一个点,addedge(src,1,0,k);最后一个点连汇点,addedge(n,sink,0,k)。
原理:构完图之后做最小费用最大流,其实就是找不大于K条增广路。如果两个区间有交集,则不能一次流过,要分成两条增广路流过;反之,则可一次流过。
1 /* 2 *Author: Zhaofa Fang 3 *Created time: 2013-07-19-10.41 4 *Language: C++ 5 */ 6 #include <cstdio> 7 #include <cstdlib> 8 #include <sstream> 9 #include <iostream> 10 #include <cmath> 11 #include <cstring> 12 #include <algorithm> 13 #include <string> 14 #include <utility> 15 #include <vector> 16 #include <queue> 17 #include <map> 18 #include <set> 19 using namespace std; 20 21 typedef long long ll; 22 typedef pair<int,int> PII; 23 #define DEBUG(x) cout<< #x << ':' << x << endl 24 #define FOR(i,s,t) for(int i = (s);i <= (t);i++) 25 #define FORD(i,s,t) for(int i = (s);i >= (t);i--) 26 #define REP(i,n) for(int i=0;i<(n);i++) 27 #define REPD(i,n) for(int i=(n-1);i>=0;i--) 28 #define PII pair<int,int> 29 #define PB push_back 30 #define MP make_pair 31 #define ft first 32 #define sd second 33 #define lowbit(x) (x&(-x)) 34 #define INF (1<<30) 35 #define eps (1e-8) 36 37 const int maxm = 5000; 38 const int maxn = 405; 39 int ans,anscost; 40 struct Edge { 41 int u,v,cost,cap,flow,next; 42 }et[maxm]; 43 int S,T; 44 int eh[maxn],tot,low[maxn],p[maxn],dist[maxn]; 45 bool vist[maxn]; 46 bool spfa(){ 47 queue<int>que; 48 memset(vist,0,sizeof(vist)); 49 memset(p,-1,sizeof(p)); 50 fill(dist,dist+maxn,INF); 51 vist[S] = 1,low[S] = INF,dist[S] = 0; 52 que.push(S); 53 while(!que.empty()){ 54 int u = que.front(); 55 que.pop(); 56 vist[u] = false; 57 for(int i=eh[u];i!=-1;i=et[i].next){ 58 int v = et[i].v,cost = et[i].cost,cap=et[i].cap,flow=et[i].flow; 59 if(flow < cap && dist[u] + cost < dist[v]){ 60 dist[v] = dist[u] + cost; 61 p[v] = i; 62 low[v] = min(low[u],cap-flow); 63 if(!vist[v]){ 64 vist[v] = 1; 65 que.push(v); 66 } 67 } 68 } 69 } 70 return dist[T]!=INF; 71 } 72 void costflow(){ 73 ans = 0,anscost = 0; 74 int num=0; 75 while(spfa()){ 76 int x = p[T]; 77 ans += low[T]; 78 anscost += low[T]*dist[T]; 79 while(x!=-1){ 80 et[x].flow += low[T]; 81 et[x^1].flow -= low[T]; 82 et[x^1].cost = -et[x].cost; 83 x = p[et[x].u]; 84 } 85 } 86 } 87 void add(int u,int v,int cost,int cap,int flow){ 88 Edge e = {u,v,cost,cap,flow,eh[u]}; 89 et[tot] = e; 90 eh[u] = tot ++; 91 } 92 void addedge(int u,int v,int cost,int cap){ 93 add(u,v,cost,cap,0);add(v,u,-cost,0,0); 94 } 95 void init(){ 96 tot = 0; 97 memset(eh,-1,sizeof(eh)); 98 } 99 int X[maxn]; 100 int a[maxn],b[maxn],w[maxn]; 101 int find(int key,int n){ 102 int r = lower_bound(X,X+n,key)-X; 103 return r+1; 104 } 105 int main(){ 106 //freopen("in","r",stdin); 107 //freopen("out","w",stdout); 108 int Ca; 109 scanf("%d",&Ca); 110 while(Ca--){ 111 int N,K; 112 scanf("%d%d",&N,&K); 113 int cnt = 0; 114 init(); 115 REP(i,N){ 116 scanf("%d%d%d",&a[i],&b[i],&w[i]); 117 X[cnt++]=a[i];X[cnt++]=b[i]; 118 w[i] = -w[i]; 119 } 120 sort(X,X+cnt); 121 int n = 1; 122 FOR(i,1,cnt-1){ 123 if(X[i]!=X[i-1])X[n++]=X[i]; 124 } 125 REP(i,n-1){ 126 addedge(i+1,i+2,0,INF); 127 } 128 REP(i,N){ 129 int l = find(a[i],n); 130 int r = find(b[i],n); 131 addedge(l,r,w[i],1); 132 } 133 addedge(0,1,0,K); 134 addedge(n,n+1,0,K); 135 S = 0;T = n+1;costflow(); 136 printf("%d\n",-anscost); 137 138 } 139 return 0; 140 }
by Farmer