POJ3680_Intervals_离散化&&最小费用流
2017-06-27 18:52
225 查看
题意
给定 N 个带权的开区间。i 号区间覆盖(ai, bi),权重为 wi。现在要从中选取一些区间,要求人一点都不被超过 K 个区间覆盖,目标是最大化总的权重。思路
讲真这个题并没有完全参透,暂且把《挑战程序设计竞赛》247页的分析贴在这吧。书中的分析没有提及离散化,实际上这一点非常重要。
题目链接
http://poj.org/problem?id=3680AC代码
#include<cstdio> #include<iostream> #include<cstring> #include<queue> #include<vector> #include<algorithm> using namespace std; typedef pair<int, int> P; struct edge { int to, cap, cost, rev; edge(int a, int b, int c, int d) :to(a), cap(b), cost(c), rev(d){} }; const int maxn = 210; const int maxv = maxn * 2; const int inf = 0x3f3f3f3f; int cas; int n, k; int A[maxn], B[maxn], C[maxn]; //保存区间信息 vector<int> X; //用于离散化 //最小费用流零件 vector<edge> G[maxv]; int dis0[maxv], dis1[maxv]; int pv[maxv], pe[maxv]; //向图中添加边 void add(int from, int to, int cap, int cost) { G[from].push_back(edge(to, cap, cost, G[to].size())); G[to].push_back(edge(from, 0, -cost, G[from].size() - 1)); } //迪杰斯特拉算法求最短路 void dijkstra(int s) { memset(dis1, inf, sizeof dis1); dis1[s] = 4000 0; priority_queue<P, vector<P>, greater<P> > qu; qu.push(P(0, s)); while(qu.size()) { P p = qu.top();qu.pop(); int v = p.second; if(dis1[v] < p.first) continue; for(int i= 0; i< G[v].size(); i++) { edge e = G[v][i]; if(e.cap > 0 && dis1[e.to] > dis1[v] + e.cost + dis0[v] - dis0[e.to]) { dis1[e.to] = dis1[v] + e.cost + dis0[v] - dis0[e.to]; pv[e.to] = v; pe[e.to] = i; qu.push(P(dis1[e.to], e.to)); } } } } //最小费用流算法 int min_cost_flow(int s, int t, int f) { int res = 0; memset(dis0, 0, sizeof dis0); while(f > 0) { dijkstra(s); if(dis1[t] == inf) return -1; for(int i= s; i<= t; i++) dis0[i] += dis1[i]; int d = f; for(int v= t; v!= s; v= pv[v]) d = min(d, G[pv[v]][pe[v]].cap); f -= d; res += d * dis0[t]; for(int v= t; v!= s; v= pv[v]) { edge &e = G[pv[v]][pe[v]]; e.cap -= d; G[e.to][e.rev].cap += d; } } return res; } int main() { cin >> cas; while(cas--) { X.clear(); for(int i= 0; i< maxv; i++) G[i].clear(); cin >> n >> k; for(int i= 0; i< n; i++) { cin >> A[i] >> B[i] >> C[i]; X.push_back(A[i]); X.push_back(B[i]); } //离散化 sort(X.begin(), X.end()); X.erase(unique(X.begin(), X.end()), X.end()); int s = 0, t = X.size() - 1; for(int i= 0; i< t; i++) add(i, i+1, inf, 0); for(int i= 0; i< n; i++) { int a = lower_bound(X.begin(), X.end(), A[i]) - X.begin(); int b = lower_bound(X.begin(), X.end(), B[i]) - X.begin(); add(a, b, 1, -C[i]); } cout << -min_cost_flow(s, t, k) << endl; } return 0; }
相关文章推荐
- POJ3680 Intervals 离散化+最小费用流
- 【POJ3680】【离散化+费用流 思维】 Intervals 区间图的最大权问题
- poj3680 Intervals 【最小费用最大流+离散化】
- POJ 2299 && HDU 3743 离散化+线段树
- pku 2528 Mayor's posters(线段树+离散化)
- POJ 2528 Mayor's posters 线段树和离散化
- POJ 3680 Intervals (拆点 || 离散) && 最大费用流
- POJ 2528 Mayor's posters(离散化+线段树)
- poj 2528 Mayor's posters(线段树 离散化 区间更新 贴海报)
- Poj 2528 Mayor's posters 线段树 离散化 成段更新
- POJ 2299 Ultra-QuickSort【逆序数&&离散化】
- POJ 2528 Mayor's posters (线段树+离散化)
- poj 2528 Mayor's posters(扫描线+堆维护||离散化+线段树)
- poj2528 Mayor's posters(线段树+离散化)
- POJ_3686_The Windy's(最小费用流)
- poj2528--Mayor's posters--离散化&查询区间的不同元素个数
- POJ 2528-Mayor's posters(线段树区间染色+离散化)
- POJ 1201 && HDU 1384 Intervals 差分约束系统
- poj2528 Mayor's posters 线段树,成段更新,离散化
- 【LeetCode】Merge Intervals && Insert Interval