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的边。
这个方法还不太理解。
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <string>
#include <cmath>
#include <queue>
#include <vector>
#include <map>
#include <set>
#include <stack>
using namespace std;
#define INF 0x3f3f3f3f
#define N 510
typedef long long LL;
struct Edge {
int u, v, nxt, cap, cost;
} edge[N*N];
int head[N], tot, pre[N], dis[N], vis[N], a[N], b[N], w[N], S, T;
vector<int> vec; void Add(int u, int v, int cap, int cost) {
edge[tot] = (Edge) { u, v, head[u], cap, cost }; head[u] = tot++;
edge[tot] = (Edge) { v, u, head[v], , -cost }; head[v] = tot++;
} bool SPFA(int S) {
queue<int> que;
que.push(S);
memset(dis, INF, sizeof(dis));
memset(vis, , sizeof(vis));
dis[S] = ; vis[S] = ;
while(!que.empty()) {
int u = que.front(); que.pop();
vis[u] = ;
for(int i = head[u]; ~i; i = edge[i].nxt) {
int v = edge[i].v, cost = edge[i].cost, cap = edge[i].cap;
if(dis[v] > dis[u] + cost && cap > ) {
dis[v] = dis[u] + cost;
pre[v] = i;
if(!vis[v]) vis[v] = , que.push(v);
}
}
}
return dis[T] < INF;
} int MFMC(int S, int T) {
int ans = , u, flow;
while(SPFA(S)) {
flow = INF, u = T;
while(u != S) {
if(flow > edge[pre[u]].cap) flow = edge[pre[u]].cap;
u = edge[pre[u]].u;
} u = T;
while(u != S) {
edge[pre[u]].cap -= flow; edge[pre[u]^].cap += flow;
ans += flow * edge[pre[u]].cost;
u = edge[pre[u]].u;
}
}
return ans;
} int main() {
int n, k, t; scanf("%d", &t);
while(t--) {
scanf("%d%d", &n, &k);
memset(head, -, sizeof(head)); tot = ;
vec.clear();
for(int i = ; i <= n; i++)
scanf("%d%d%d", &a[i], &b[i], &w[i]), vec.push_back(a[i]), vec.push_back(b[i]);
sort(vec.begin(), vec.end());
vec.erase(unique(vec.begin(), vec.end()), vec.end()); // 新的离散化姿势
int cnt = vec.size();
S = , T = cnt + ;
int ans = ; // First
Add(S, , k, ); Add(cnt, T, k, );
for(int i = ; i < cnt; i++) Add(i, i + , INF, );
for(int i = ; i <= n; i++) {
int u = lower_bound(vec.begin(), vec.end(), a[i]) - vec.begin() + ;
int v = lower_bound(vec.begin(), vec.end(), b[i]) - vec.begin() + ;
Add(u, v, , -w[i]);
}
ans -= MFMC(S, T); // Second
// Add(S, 1, k, 0); Add(cnt, T, k, 0);
// for(int i = 1; i < cnt; i++) Add(i, i + 1, INF, 0);
// for(int i = 1; i <= n; i++) {
// int u = lower_bound(vec.begin(), vec.end(), a[i]) - vec.begin() + 1;
// int v = lower_bound(vec.begin(), vec.end(), b[i]) - vec.begin() + 1;
// Add(S, v, 1, 0); Add(u, T, 1, 0);
// Add(v, u, 1, w[i]);
// ans += w[i];
// }
// ans -= MFMC(S, T);
printf("%d\n", ans);
}
return ;
} /*
3 1
1 2 2
2 3 4
3 4 8
3 1
1 3 2
2 3 4
3 4 8
3 2
1 100000 100000
1 150 301
100 200 300
*/
POJ 3680:Intervals(最小费用最大流)***的更多相关文章
- POJ 3680 Intervals 最小费用最大流(MCMF算法)
题意:给出 n ,k 表示接下来给你 n 段开区间,每段区间都有它的权值,问选出一些区间,使它的权值最大,并且在实轴上的每个点,不得超过 k次被覆盖. 思路:首先要理解建图思路,首先有一个基图,相邻点 ...
- POJ 3680 Intervals(费用流)
Intervals Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 5762 Accepted: 2288 Descrip ...
- POJ 3680 Intervals(费用流+负权优化)
[题目链接] http://poj.org/problem?id=3680 [题目大意] 有N个带权重的区间,现在要从中选取一些区间, 要求任意点都不被超过K个区间所覆盖,请最大化总的区间权重. [题 ...
- Going Home POJ - 2195 (最小费用最大流)
On a grid map there are n little men and n houses. In each unit time, every little man can move one ...
- poj 3680 Intervals(费用流)
http://poj.org/problem?id=3680 巧妙的构图. 题目:给定N个区间(ai,bi)权值wi,求最大权和且每个点最多覆盖K次. 构图:将区间端点离散化,将第i个点连第i+1个点 ...
- poj3680 Intervals 区间k覆盖问题 最小费用最大流 建图巧妙
/** 题目:poj3680 Intervals 区间k覆盖问题 最小费用最大流 建图巧妙 链接:http://poj.org/problem?id=3680 题意:给定n个区间,每个区间(ai,bi ...
- POJ 2195:Going Home(最小费用最大流)
http://poj.org/problem?id=2195 题意:有一个地图里面有N个人和N个家,每走一格的花费是1,问让这N个人分别到这N个家的最小花费是多少. 思路:通过这个题目学了最小费用最大 ...
- poj 2195 二分图带权匹配+最小费用最大流
题意:有一个矩阵,某些格有人,某些格有房子,每个人可以上下左右移动,问给每个人进一个房子,所有人需要走的距离之和最小是多少. 貌似以前见过很多这样类似的题,都不会,现在知道是用KM算法做了 KM算法目 ...
- POJ 2157 Evacuation Plan [最小费用最大流][消圈算法]
---恢复内容开始--- 题意略. 这题在poj直接求最小费用会超时,但是题意也没说要求最优解. 根据线圈定理,如果一个跑完最费用流的残余网络中存在负权环,那么顺着这个负权环跑流量为1那么会得到更小的 ...
- POJ 2195 Going Home(最小费用最大流)
http://poj.org/problem?id=2195 题意 : N*M的点阵中,有N个人,N个房子.让x个人走到这x个房子中,只能上下左右走,每个人每走一步就花1美元,问当所有的人都归位了之 ...
随机推荐
- 许多其他C++的class样本
class A{ public: A(){}//构造函数,作用分配类所需的空间 }; int main() { A a; } a它是类A示例! 版权声明:本文博客原创文章.博客,未经同意,不得转 ...
- Android手势识别的发展
在播放器.与手势识别.所以,看看今天的我们Android手势识别. 首先,我们需要站在巨人的肩膀上.有些人举了个例子和说明. 第一章: http://www.2cto.com/kf/201110/10 ...
- WPF中实现PropertyGrid(用于展示对象的详细信息)的三种方式
原文:WPF中实现PropertyGrid(用于展示对象的详细信息)的三种方式 由于WPF中没有提供PropertyGrid控件,有些业务需要此类的控件.这篇文章介绍在WPF中实现PropertyGr ...
- WPF自定义控件步骤
1 .在类库里面添加system.xaml的引用,给控件指定Name: 2.设计控件的外观,并将内部元素绑定到控件类的属性:此时即使没有在类中增加相关属性也不会报错,xaml类似html错误只是不显示 ...
- Rxjava 学习(一)
Rxjava是什么? RxJava是由Netflix开发的响应式扩展(Reactive Extensions)的Java实现.引用MSDN上对它的定义,Reactive Extensions是这样一个 ...
- WPF 资源(StaticResource 静态资源、DynamicResource 动态资源、添加二进制资源、绑定资源树)
原文:WPF 资源(StaticResource 静态资源.DynamicResource 动态资源.添加二进制资源.绑定资源树) 一.WPF对象级(Window对象)资源的定义与查找 实例一: St ...
- 你遗忘的都在这里—iOS常用类型方法笔记
这些都是项目中常用但又常忘的方法,与大家分享一下. 一.NSString 创建字符串. NSString *astring = @"This is a String!"; 创建空 ...
- 用TTcpClient和TTcpServer进行文件的传输
发送数据时有Sendln,SendBuf,SendStream.接收数据时有Receiveln,ReceiveBuf,当时我很奇怪为什么没有ReceiveStream.因为很自然的想到是对应关系的.但 ...
- Tomcat cache 缓存 编译
http://tomcat.apache.org/tomcat-7.0-doc/jasper-howto.html development - Is Jasper used in developmen ...
- 使用Boost的DLL库管理动态链接库
Boost 1.61新增了一个DLL库,跟Qt中的QLibrary类似,提供了跨平台的动态库链接库加载.调用等功能.http://www.boost.org/users/history/version ...