http://poj.org/problem?id=3680

巧妙的构图。

题目:给定N个区间(ai,bi)权值wi,求最大权和且每个点最多覆盖K次。

构图:将区间端点离散化,将第i个点连第i+1个点花费为0,容量为INF,即addedge(i,i+1,0,INF)(可用来跳过一些区间);

   再处理N个区间(ai,bi),addedge(ai,bi,-wi,1);

   最后源点连第一个点,addedge(src,1,0,k);最后一个点连汇点,addedge(n,sink,0,k)。

原理:构完图之后做最小费用最大流,其实就是找不大于K条增广路。如果两个区间有交集,则不能一次流过,要分成两条增广路流过;反之,则可一次流过。

 /*
*Author: Zhaofa Fang
*Created time: 2013-07-19-10.41
*Language: C++
*/
#include <cstdio>
#include <cstdlib>
#include <sstream>
#include <iostream>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <string>
#include <utility>
#include <vector>
#include <queue>
#include <map>
#include <set>
using namespace std; typedef long long ll;
typedef pair<int,int> PII;
#define DEBUG(x) cout<< #x << ':' << x << endl
#define FOR(i,s,t) for(int i = (s);i <= (t);i++)
#define FORD(i,s,t) for(int i = (s);i >= (t);i--)
#define REP(i,n) for(int i=0;i<(n);i++)
#define REPD(i,n) for(int i=(n-1);i>=0;i--)
#define PII pair<int,int>
#define PB push_back
#define MP make_pair
#define ft first
#define sd second
#define lowbit(x) (x&(-x))
#define INF (1<<30)
#define eps (1e-8) const int maxm = ;
const int maxn = ;
int ans,anscost;
struct Edge {
int u,v,cost,cap,flow,next;
}et[maxm];
int S,T;
int eh[maxn],tot,low[maxn],p[maxn],dist[maxn];
bool vist[maxn];
bool spfa(){
queue<int>que;
memset(vist,,sizeof(vist));
memset(p,-,sizeof(p));
fill(dist,dist+maxn,INF);
vist[S] = ,low[S] = INF,dist[S] = ;
que.push(S);
while(!que.empty()){
int u = que.front();
que.pop();
vist[u] = false;
for(int i=eh[u];i!=-;i=et[i].next){
int v = et[i].v,cost = et[i].cost,cap=et[i].cap,flow=et[i].flow;
if(flow < cap && dist[u] + cost < dist[v]){
dist[v] = dist[u] + cost;
p[v] = i;
low[v] = min(low[u],cap-flow);
if(!vist[v]){
vist[v] = ;
que.push(v);
}
}
}
}
return dist[T]!=INF;
}
void costflow(){
ans = ,anscost = ;
int num=;
while(spfa()){
int x = p[T];
ans += low[T];
anscost += low[T]*dist[T];
while(x!=-){
et[x].flow += low[T];
et[x^].flow -= low[T];
et[x^].cost = -et[x].cost;
x = p[et[x].u];
}
}
}
void add(int u,int v,int cost,int cap,int flow){
Edge e = {u,v,cost,cap,flow,eh[u]};
et[tot] = e;
eh[u] = tot ++;
}
void addedge(int u,int v,int cost,int cap){
add(u,v,cost,cap,);add(v,u,-cost,,);
}
void init(){
tot = ;
memset(eh,-,sizeof(eh));
}
int X[maxn];
int a[maxn],b[maxn],w[maxn];
int find(int key,int n){
int r = lower_bound(X,X+n,key)-X;
return r+;
}
int main(){
//freopen("in","r",stdin);
//freopen("out","w",stdout);
int Ca;
scanf("%d",&Ca);
while(Ca--){
int N,K;
scanf("%d%d",&N,&K);
int cnt = ;
init();
REP(i,N){
scanf("%d%d%d",&a[i],&b[i],&w[i]);
X[cnt++]=a[i];X[cnt++]=b[i];
w[i] = -w[i];
}
sort(X,X+cnt);
int n = ;
FOR(i,,cnt-){
if(X[i]!=X[i-])X[n++]=X[i];
}
REP(i,n-){
addedge(i+,i+,,INF);
}
REP(i,N){
int l = find(a[i],n);
int r = find(b[i],n);
addedge(l,r,w[i],);
}
addedge(,,,K);
addedge(n,n+,,K);
S = ;T = n+;costflow();
printf("%d\n",-anscost); }
return ;
}

1300+MS

poj 3680 Intervals(费用流)的更多相关文章

  1. POJ 3680: Intervals【最小费用最大流】

    题目大意:你有N个开区间,每个区间有个重量wi,你要选择一些区间,使得满足:每个点被不超过K个区间覆盖的前提下,重量最大 思路:感觉是很好想的费用流,把每个区间首尾相连,费用为该区间的重量的相反数(由 ...

  2. poj 3680(最小费用最大流)

    题目链接:http://poj.org/problem?id=3680 思路:因为N<=200,而区间范围为[1,100000],因此需要离散化,去重,然后就是建图了相连两点连边,容量为k,费用 ...

  3. POJ 2516 基础费用流

    题意       有n个顾客,m个供应商,k种货物,给你顾客对于每种货物的要求个数,和供应商对于每种货物的现有量,以及供应每种货物的时候供应商和顾客之间的运输单价,问你满足所有顾客的前提下的最小运输费 ...

  4. POJ 2135 简单费用流

    题意:       题意是一个人他要从牧场1走到牧场n然后在走回来,每条路径只走一次,问全程的最短路径是多少. 思路:        这个题目挺简单的吧,首先要保证每条边只能走一次,然后还要要求费用最 ...

  5. POJ 3680 Intervals(费用流)

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

  6. 网络流(最大费用最大流) :POJ 3680 Intervals

    Intervals Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 7218   Accepted: 3011 Descrip ...

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

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

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

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

  9. poj 3680 Intervals

    给定N个带权的开区间,第i个区间覆盖区间(ai,bi),权值为wi.现在要求挑出一些区间使得总权值最大,并且满足实轴上任意一个点被覆盖不超过K次. 1<=K<=N<=200.1< ...

随机推荐

  1. linux查看系统的日志的一些实用操作

    last -a 把从何处登入系统的主机名称或ip地址,显示在最后一行. -d 指定记录文件.指定记录文件.将IP地址转换成主机名称. -f <记录文件> 指定记录文件. -n <显示 ...

  2. modbus rtu 协议转DLT645-2007和DLT645-1997电表协议转换器定制,

    现场会碰到现场数据为Modbus协议,但是后台系统为DLT645协议系统,本模块支持将工业ModbusRtu协议转换为电表国标协议DLT645协议,支持1997和2007俩种标准,只需要进行简单的配置 ...

  3. 新手必看:如何快速看懂VC++项目

    1.在具备必需的编程基础知识后,试图理解一份完整的代码可以从以下几个方面入手:   1)首先运行以下程序,从外部角度感受一下有哪些功能.  2)了解代码中每个类的功能.看看文档,或者类的注释,那么仅仅 ...

  4. #include <strstream>

    std::ostrstream MYOUT(str, sizeof(str)); 拼接字符串 #include <iostream> #include <strstream> ...

  5. Sass介绍及入门教程

    Sass是什么? Sass是"Syntactically Awesome StyleSheets"的简称.那么他是什么?其实没有必要太过于纠结,只要知道他是“CSS预处理器”中的一 ...

  6. Android源码学习(一) 数据集观察者

    查看Android源码发现这个,决定记下下来. 1.在android.database这个包下面,存在这样一个抽象类DataSetObserver,里面包括onChanged()和onInvalida ...

  7. C#委托,事件,匿名委托

    作为一个初学者,写下来是当做自己的学习笔记,希望在以后遇到问题的时候能够快速的找到方法 如果能帮助跟我一样的新人是更好不过的了        如果有什么不正确或者可以改进的地方也希望大家能够指出来  ...

  8. EC读书笔记系列之3:条款5、条款6、条款7

    条款5:了解C++默默编写并调用哪些函数 记住: ★编译器可以(仅仅是可以,并非必须,仅当程序中有这样的用法时才会这么做!!!)暗自为class创建default构造函数,copy构造函数,copy ...

  9. leetcode Jump Game II python

    @link http://www.cnblogs.com/zuoyuan/p/3781953.htmlGiven an array of non-negative integers, you are ...

  10. Linux学习之sed命令详解

    概述 sed是stream editor的简称,也就是流编辑器.它一次处理一行内容,处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”(pattern space),接着用sed命令处理缓冲区 ...