POJ 3680 Intervals

传说中的区间k覆盖问题。

给定n个带权开区间,选择其中一些使得区间权值之和最大,且所有区间内任意点被覆盖不能超过k次。

建图方法:

1.将区间离散化,对于离散化后的区间端点所对应的点i,i+1,加边(i,i+1,k,0)

2.对于每个区间(a,b),所对应离散化后的点(xx,yy),加边(xx,yy,-w,1),w为区间的权值

3.由源点src连一条到一个点的边(src,1,k,0),同理,由最后一个点t连一条道汇点sink的边(t,sink,k,0)

跑一遍最小费用了取反即为结果。

  1 #include <cstdio>
  2 #include <algorithm>
  3 #include <cstring>
  4 #include <queue>
  5 #define maxn 410
  6 #define maxm 2010
  7 #define INF 1<<30
  8 using namespace std;
  9 struct MCMF{
 10     int src,sink,e,n;
 11     int first[maxn];
 12     int cap[maxm],cost[maxm],v[maxm],next[maxm];
 13     bool flag;
 14     void init(){
 15         e = 0;
 16         memset(first,-1,sizeof(first));
 17     }
 18 
 19     void add_edge(int a,int b,int cc,int ww){
 20         //printf("add:%d to %d,cap = %d,cost = %d
",a,b,cc,ww);
 21         cap[e] = cc;cost[e] = ww;v[e] = b;
 22         next[e] = first[a];first[a] = e++;
 23         cap[e] = 0;cost[e] = -ww;v[e] = a;
 24         next[e] = first[b];first[b] = e++;
 25     }
 26 
 27     int d[maxn],pre[maxn],pos[maxn];
 28     bool vis[maxn];
 29 
 30     bool spfa(int s,int t){
 31         memset(pre,-1,sizeof(pre));
 32         memset(vis,0,sizeof(vis));
 33         queue<int> Q;
 34         for(int i = 0;i <= n;i++)   d[i] = INF;
 35         Q.push(s);pre[s] = s;d[s] = 0;vis[s] = 1;
 36         while(!Q.empty()){
 37             int u = Q.front();Q.pop();
 38             vis[u] = 0;
 39             for(int i = first[u];i != -1;i = next[i]){
 40                 if(cap[i] > 0 && d[u] + cost[i] < d[v[i]]){
 41                     d[v[i]] = d[u] + cost[i];
 42                     pre[v[i]] = u;pos[v[i]] = i;
 43                     if(!vis[v[i]])  vis[v[i]] = 1,Q.push(v[i]);
 44                 }
 45             }
 46         }
 47         return pre[t] != -1;
 48     }
 49 
 50     int Mincost;
 51     int Maxflow;
 52 
 53     int MinCostFlow(int s,int t,int nn){
 54         Mincost = 0,Maxflow = 0,n = nn;
 55         while(spfa(s,t)){
 56             int min_f = INF;
 57             for(int i = t;i != s;i = pre[i])
 58                 if(cap[pos[i]] < min_f) min_f = cap[pos[i]];
 59             Mincost += d[t] * min_f;
 60             Maxflow += min_f;
 61             for(int i = t;i != s;i = pre[i]){
 62                 cap[pos[i]] -= min_f;
 63                 cap[pos[i]^1] += min_f;
 64             }
 65         }
 66         return Mincost;
 67     }
 68 };
 69 MCMF g;
 70 
 71 struct Line{
 72     int a,b,w;
 73 }line[210];
 74 int x[410];
 75 
 76 int main(){
 77     int T;
 78     scanf("%d",&T);
 79     while(T--){
 80         g.init();
 81         int N,K;
 82         scanf("%d%d",&N,&K);
 83         int cnt = 0;
 84         for(int i = 0;i < N;i++){
 85             int a,b,w;
 86             scanf("%d%d%d",&a,&b,&w);
 87             x[cnt++] = a;x[cnt++] = b;
 88             line[i].a = a;line[i].b = b;line[i].w = w;
 89         }
 90         sort(x,x+cnt);
 91         int t = unique(x,x+cnt) - x;
 92         //printf("t = %d
",t);
 93         for(int i = 0;i < N;i++){
 94             int xx = lower_bound(x,x+t,line[i].a) - x + 1;
 95             int yy = lower_bound(x,x+t,line[i].b) - x + 1;
 96             g.add_edge(xx,yy,1,-line[i].w);
 97         }
 98         for(int i = 1;i < t;i++){
 99             g.add_edge(i,i+1,K,0);
100         }
101         int src = t+1,sink = src+1;
102         g.add_edge(src,1,K,0);
103         g.add_edge(t,sink,K,0);
104         int ans = g.MinCostFlow(src,sink,sink);
105         printf("%d
",-ans);
106     }
107     return 0;
108 }
View Code
原文地址:https://www.cnblogs.com/zhexipinnong/p/3356862.html