poj 3680 Intervals(费用流)

时间:2022-05-26 16:20:35

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条增广路。如果两个区间有交集,则不能一次流过,要分成两条增广路流过;反之,则可一次流过。

poj 3680 Intervals(费用流)poj 3680 Intervals(费用流)
  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 }
1300+MS