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 }
1300+MS

 

你可能感兴趣的:(poj)