POJ 3680:Intervals(最小费用最大流)***

http://poj.org/problem?id=3680

题意:给出n个区间[Li,Ri],每个区间有一个权值wi,要使得每个点都不被超过k个区间覆盖(最多能被k个区间覆盖),如果选取了第i个区间,那么能得到wi的权值,问最终能得到的最大权值是多少。

思路:首先把区间离散化,然后考虑构图。

第一种构图方式:

将S到第一个区间结点连一条容量为k,费用为0的边,代表最多能使用k个区间。

对于每个区间[l,r],从l到r连一条容量为1,费用为-w[i]的边(因为跑的是最大的费用),这里如果这条边的流量为1,那么代表使用了这个区间,那么就加上费用。

将最后一个区间结点连一条容量为k,费用为0的边,同S。

对于每个离散化后的区间,将i和i+1连一条容量为INF,费用为0的边,如果不跑这条边,那么说明这段区间被覆盖了。

最后将答案取反就是最终答案。

画了个图帮助理解:如果跑1->3的区间的话,那么1->3的流量是1,那么主路径在[1,3]的时候流量为k-1,然后跑2->4,主路径在[2,3]的流量就变成k-2,跑到3的时候就变回k-1,跑到4又变回k,如果k=0的时候,那么就不能被覆盖了,因此恰好可以满足限制。

第二种构图方式:

是挑战上的,对于有负权边的构图。

S和T和i到i+1的连边和上图一样。

对于[u,v],S到v连一条容量为1,费用为0的边,u到T连一条容量为1,费用为0的边,v到u连一条容量为1,费用为wi的边。

这个方法还不太理解。

  1 #include <cstdio>
  2 #include <algorithm>
  3 #include <iostream>
  4 #include <cstring>
  5 #include <string>
  6 #include <cmath>
  7 #include <queue>
  8 #include <vector>
  9 #include <map>
 10 #include <set>
 11 #include <stack>
 12 using namespace std;
 13 #define INF 0x3f3f3f3f
 14 #define N 510
 15 typedef long long LL;
 16 struct Edge {
 17     int u, v, nxt, cap, cost;
 18 } edge[N*N];
 19 int head[N], tot, pre[N], dis[N], vis[N], a[N], b[N], w[N], S, T;
 20 vector<int> vec;
 21 
 22 void Add(int u, int v, int cap, int cost) {
 23     edge[tot] = (Edge) { u, v, head[u], cap, cost }; head[u] = tot++;
 24     edge[tot] = (Edge) { v, u, head[v], 0, -cost }; head[v] = tot++;
 25 }
 26 
 27 bool SPFA(int S) {
 28     queue<int> que;
 29     que.push(S);
 30     memset(dis, INF, sizeof(dis));
 31     memset(vis, 0, sizeof(vis));
 32     dis[S] = 0; vis[S] = 1;
 33     while(!que.empty()) {
 34         int u = que.front(); que.pop();
 35         vis[u] = 0;
 36         for(int i = head[u]; ~i; i = edge[i].nxt) {
 37             int v = edge[i].v, cost = edge[i].cost, cap = edge[i].cap;
 38             if(dis[v] > dis[u] + cost && cap > 0) {
 39                 dis[v] = dis[u] + cost;
 40                 pre[v] = i;
 41                 if(!vis[v]) vis[v] = 1, que.push(v);
 42             }
 43         }
 44     }
 45     return dis[T] < INF;
 46 }
 47 
 48 int MFMC(int S, int T) {
 49     int ans = 0, u, flow;
 50     while(SPFA(S)) {
 51         flow = INF, u = T;
 52         while(u != S) {
 53             if(flow > edge[pre[u]].cap) flow = edge[pre[u]].cap;
 54             u = edge[pre[u]].u;
 55         } u = T;
 56         while(u != S) {
 57             edge[pre[u]].cap -= flow; edge[pre[u]^1].cap += flow;
 58             ans += flow * edge[pre[u]].cost;
 59             u = edge[pre[u]].u;
 60         }
 61     }
 62     return ans;
 63 }
 64 
 65 int main() {
 66     int n, k, t; scanf("%d", &t);
 67     while(t--) {
 68         scanf("%d%d", &n, &k);
 69         memset(head, -1, sizeof(head)); tot = 0;
 70         vec.clear();
 71         for(int i = 1; i <= n; i++)
 72             scanf("%d%d%d", &a[i], &b[i], &w[i]), vec.push_back(a[i]), vec.push_back(b[i]);
 73         sort(vec.begin(), vec.end());
 74         vec.erase(unique(vec.begin(), vec.end()), vec.end()); // 新的离散化姿势
 75         int cnt = vec.size();
 76         S = 0, T = cnt + 1;
 77         int ans = 0;
 78 
 79 //      First
 80         Add(S, 1, k, 0); Add(cnt, T, k, 0);
 81         for(int i = 1; i < cnt; i++) Add(i, i + 1, INF, 0);
 82         for(int i = 1; i <= n; i++) {
 83             int u = lower_bound(vec.begin(), vec.end(), a[i]) - vec.begin() + 1;
 84             int v = lower_bound(vec.begin(), vec.end(), b[i]) - vec.begin() + 1;
 85             Add(u, v, 1, -w[i]);
 86         }
 87         ans -= MFMC(S, T);
 88 
 89 //        Second
 90 //        Add(S, 1, k, 0); Add(cnt, T, k, 0);
 91 //        for(int i = 1; i < cnt; i++) Add(i, i + 1, INF, 0);
 92 //        for(int i = 1; i <= n; i++) {
 93 //            int u = lower_bound(vec.begin(), vec.end(), a[i]) - vec.begin() + 1;
 94 //            int v = lower_bound(vec.begin(), vec.end(), b[i]) - vec.begin() + 1;
 95 //            Add(S, v, 1, 0); Add(u, T, 1, 0);
 96 //            Add(v, u, 1, w[i]);
 97 //            ans += w[i];
 98 //        }
 99 //        ans -= MFMC(S, T);
100         printf("%d
", ans);
101     }
102     return 0;
103 }
104 
105 /*
106 3 1
107 1 2 2
108 2 3 4
109 3 4 8
110 3 1
111 1 3 2
112 2 3 4
113 3 4 8
114 3 2
115 1 100000 100000
116 1 150 301
117 100 200 300
118 */
原文地址:https://www.cnblogs.com/fightfordream/p/6751750.html