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(最小费用最大流)***的更多相关文章

  1. POJ 3680 Intervals 最小费用最大流(MCMF算法)

    题意:给出 n ,k 表示接下来给你 n 段开区间,每段区间都有它的权值,问选出一些区间,使它的权值最大,并且在实轴上的每个点,不得超过 k次被覆盖. 思路:首先要理解建图思路,首先有一个基图,相邻点 ...

  2. POJ 3680 Intervals(费用流)

    Intervals Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 5762   Accepted: 2288 Descrip ...

  3. POJ 3680 Intervals(费用流+负权优化)

    [题目链接] http://poj.org/problem?id=3680 [题目大意] 有N个带权重的区间,现在要从中选取一些区间, 要求任意点都不被超过K个区间所覆盖,请最大化总的区间权重. [题 ...

  4. 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 ...

  5. poj 3680 Intervals(费用流)

    http://poj.org/problem?id=3680 巧妙的构图. 题目:给定N个区间(ai,bi)权值wi,求最大权和且每个点最多覆盖K次. 构图:将区间端点离散化,将第i个点连第i+1个点 ...

  6. poj3680 Intervals 区间k覆盖问题 最小费用最大流 建图巧妙

    /** 题目:poj3680 Intervals 区间k覆盖问题 最小费用最大流 建图巧妙 链接:http://poj.org/problem?id=3680 题意:给定n个区间,每个区间(ai,bi ...

  7. POJ 2195:Going Home(最小费用最大流)

    http://poj.org/problem?id=2195 题意:有一个地图里面有N个人和N个家,每走一格的花费是1,问让这N个人分别到这N个家的最小花费是多少. 思路:通过这个题目学了最小费用最大 ...

  8. poj 2195 二分图带权匹配+最小费用最大流

    题意:有一个矩阵,某些格有人,某些格有房子,每个人可以上下左右移动,问给每个人进一个房子,所有人需要走的距离之和最小是多少. 貌似以前见过很多这样类似的题,都不会,现在知道是用KM算法做了 KM算法目 ...

  9. POJ 2157 Evacuation Plan [最小费用最大流][消圈算法]

    ---恢复内容开始--- 题意略. 这题在poj直接求最小费用会超时,但是题意也没说要求最优解. 根据线圈定理,如果一个跑完最费用流的残余网络中存在负权环,那么顺着这个负权环跑流量为1那么会得到更小的 ...

  10. POJ 2195 Going Home(最小费用最大流)

    http://poj.org/problem?id=2195 题意 :  N*M的点阵中,有N个人,N个房子.让x个人走到这x个房子中,只能上下左右走,每个人每走一步就花1美元,问当所有的人都归位了之 ...

随机推荐

  1. Swift 中使用 SwiftyJSON 制作一个比特币价格 APP

    Swift 中处理 JSON 数据有很多种方式,可以使用原生的 NSJSONSerialization,也可以使用很多第三方库.原生的 NSJSONSerialization 方式这篇文章中介绍过.这 ...

  2. SICP 1.17-1.19

    1.16 -------------> 不考虑0的情况 <------------ (define (fe b n) (define (fet m c) (cond ((= m n) c) ...

  3. SQL Server 命名实例更改端口进行发布订阅

    原文:SQL Server 命名实例更改端口进行发布订阅 两台数据库服务器,都没有加入域,都安装多实例,端口也不一样了.现在使用命名实例进行复制,折腾了好久,才发现解决方法. 服务器A:myserve ...

  4. 关于SetLocaleInfo()

    原文:关于SetLocaleInfo() 此函数用于设置系统的一些本地信息, 非常有用. 比如日期格式为'yyyy/mm/dd'时, 稍微不注意,有些程序语句会报错. 以下资料网络收集: 1. Set ...

  5. Android零基础入门第86节:探究Fragment生命周期

    一个Activity可以同时组合多个Fragment,一个Fragment也可被多个Activity 复用.Fragment可以响应自己的输入事件,并拥有自己的生命周期,但它们的生命周期直接被其所属的 ...

  6. Android实现dialog时候弹出软键盘dialog移位问题

    Window win = getWindow(); WindowManager.LayoutParams params = win.getAttributes(); win.setSoftInputM ...

  7. Qt通过HTTP POST上传文件(python做服务端,附下载)

    本文使用Qt Creator用HTTP POST的方法上传文件,并给出一个上传文件的例程. 本文主要客户端,所以对于服务器端程序编写的描述会比较简略 服务器使用Django编写,django服务器接收 ...

  8. Markdown 语法简体中文版

    Markdown 语法简体中文版(fork 于繁体中文版 http://markdown.tw/ ) http://wowubuntu.com/markdownhttps://github.com/r ...

  9. MFC 中 Tooltip 实现的几种方式

    方法一:利用CWnd本身自身支持的tooptip来实现,这种方法适用给控件增加tooltip,非常方便和简单方法如下:1.在窗口中增加消息映射ON_NOTIFY_EX(TTN_NEEDTEXT, 0, ...

  10. Codility--- Distinct

    Task description Write a function class Solution { public int solution(int[] A); } that, given a zer ...