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\n", 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 */