POJ 3690 Intervals 费用流 最大变最小
来源:互联网 发布:linux 打包压缩文件夹 编辑:程序博客网 时间:2024/04/30 10:39
题意:给出N个开区间。每个区间有一个权重。问题:让你选出多个区间,最大化总权重,同时,每个点至多被包含k次。
思路:首先,因为区间的个数不多,但是区间的范围比较大,我们要离散化区间端点。接下来的都是对离散化的点进行的操作。
当K= 1时,这个题等价于从N个区间选出一个元素互不相交的子集。这将变成简单的DP,即01背包问题。
当K>1时,我们能否贪心的选1次互不相交的区间组成的子集,删掉相应的区间,然后对剩下的区间同样重复处理K次呢?
实践后发现,这样是不行的,我们仅仅选出了局部最优解,但不是全局最优解。换句话说,我们需要反悔。这个时候是否想到了网络流呢?
因为要求最大权,我们要用费用流。因为是要求最大费用,而费用流是求最小费用,我们可以利用取负的方法求出最小费用,然后再取负,就是最终的答案。
我们先整理一下题中给出的条件:1.n个开区间,每个区间有选不选两种选择,选就会有对应的权重。2.每个点至多包含k次。
所以建图方法如下:
1.增设源点S,汇点T,S向第一个端点连容量为K,费用为0的边。最后一个端点向T连容量为K,费用为0的边。
2.每个端点向向后一个端点连费用为0,容量为无穷大的边。
3.对于每个区间,从左端点向右端点连容量为1,费用为-cost的边。
然后对整个图跑最小费用流,即可。
代码如下:
#include <cstdio>#include <algorithm>#include <queue>#include <utility>#include <cstring>using namespace std;typedef pair<int,int> pii;template<class T>inline bool read(T &n){T x = 0, tmp = 1; char c = getchar();while ((c < '0' || c > '9') && c != '-' && c != EOF) c = getchar();if (c == EOF) return false;if (c == '-') c = getchar(), tmp = -1;while (c >= '0' && c <= '9') x *= 10, x += (c - '0'), c = getchar();n = x*tmp;return true;}struct zkw_flow{ static const int MAX = 20000; static const int INF = 0x3f3f3f3f; struct edge{ int from,to,cap,flow,cost; edge(int u=0, int v=0, int c=0, int f=0, int w=0): from(u),to(v),cap(c),flow(f),cost(w){} } edges[2 * MAX]; int head[MAX],next[MAX],tot; int dis[MAX]; bool used[MAX]; int src,sink,n; int cost,flow; priority_queue<pii> Q; void init(int n){ this->n = n; memset(head,-1,sizeof(head)); tot = 0; } void addedge(int u, int v, int c, int w){ edges[tot] = edge(u,v,c,0,w); next[tot] = head[u], head[u] = tot++; edges[tot] = edge(v,u,0,0,-w); next[tot] = head[v], head[v] = tot++; } void spfa(){ memset(dis,0x3f,sizeof(dis)); dis[src] = 0; Q.push(make_pair(0,src)); while(!Q.empty()){ pii p = Q.top();Q.pop(); int u = p.second, d = -p.first; if(dis[u] != d) continue; for(int v = head[u]; ~v ; v = next[v]){ edge & e = edges[v]; if(e.cap > e.flow && dis[e.to] > d + e.cost){ dis[e.to] = d + e.cost; Q.push(make_pair(-dis[e.to],e.to)); } } } for(int i = 0 ; i < n; ++i) dis[i] = dis[sink] - dis[i]; } int augment(int u,int f){ if(u == sink){ flow += f; cost += dis[src] * f; return f; } used[u] = true; int now = f; for(int v = head[u]; ~v; v = next[v]){ edge & e = edges[v]; if(e.cap > e.flow && !used[e.to] && dis[u] == dis[e.to] + e.cost){ int tmp = augment(e.to,min(now,e.cap - e.flow)); e.flow += tmp; edges[v^1].flow -= tmp; now -= tmp; if(now == 0) break; } } return f - now; } bool modify(){ int d = INF; for(int u = 0 ; u < n; ++u) if(used[u]) for(int v = head[u]; ~v; v = next[v]){ edge&e = edges[v]; if(e.cap > e.flow && !used[e.to]) d = min(d, dis[e.to] + e.cost - dis[u]); } if(d == INF) return false; for(int i = 0; i < n; ++i) if(used[i]) dis[i] += d; return true; } int mincost(int s,int t){ src = s, sink = t; flow = cost = 0; spfa(); for(;;){ for(;;){ memset(used,0,sizeof(used)); if(!augment(src,INF)) break; } if(!modify()) break; } return cost; }} solver;const int MAX = 200;const int INF = 0x3f3f3f3f;int T,K,N;int a[MAX],b[MAX],w[MAX];int main(void){ //freopen("input.txt","r",stdin); read(T); while(T--){ read(N),read(K); vector<int> x; for(int i = 0 ; i < N; ++i){ read(a[i]),read(b[i]),read(w[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 m = x.size(); int s = m, t = s + 1; solver.init(m + 2); int res = 0; solver.addedge(s,0,K,0); solver.addedge(m-1,t,K,0); for(int i = 0 ; i + 1 < m; ++i) solver.addedge(i,i+1,INF,0); for(int i = 0 ; i < N; ++i){ int u = lower_bound(x.begin(),x.end(),a[i]) - x.begin(); int v = lower_bound(x.begin(),x.end(),b[i]) - x.begin(); solver.addedge(u,v,1,-w[i]); } printf("%d\n",-solver.mincost(s,t)); } return 0;}
0 0
- POJ 3690 Intervals 费用流 最大变最小
- POJ Intervals (最小费用最大流)
- poj 3680 Intervals (最小费用最大流)
- Intervals poj 3680 最小费用最大流
- POJ 3680 Intervals (最小费用最大流+离散化)
- Intervals (poj 3680 离散化+最小费用最大流)
- 【POJ3680】Intervals 最小费用最大流
- POJ 3680 Intervals(最小费用流)
- POJ 3680 Intervals(最小费用流)
- poj 3680 Intervals 最大费用流
- Intervals----最小费用流
- POJ 3680 Intervals (最大费用最大流)
- poj3680 Intervals 【最小费用最大流+离散化】
- poj 3680 Intervals(最大费用流+离散化)
- POJ 3680Intervals (拆点 || 离散) && 最大费用流
- poj 2516 最小费用最大流
- poj/pku 3680(最小费用最大流)
- 【最小费用最大流】POJ 2516【unsolved】
- Java基础---运算符
- 2048中需要使用的逻辑
- java实现后台自动发邮件功能
- android 自定义view中onMeasure()理解
- JVM性能调优
- POJ 3690 Intervals 费用流 最大变最小
- hdu 4730 We Love MOE Girls(水题)
- 给晕针的童鞋一些参考
- O(N lgK) 时间内合并K个有序链表
- 《MFC游戏开发》笔记二 建立工程、调整窗口
- java-- 学生介绍
- 跳转到系统短信界面和预设短信内容
- Codeforces Round #265 (Div. 2)D(判断立方体)
- android学习笔记【1】KEYCODE列表