«问题描述:

«编程任务:
对于给定的开区间集合I和正整数k,计算开区间集合I的最长k可重区间集的长度。
«数据输入:
由文件interv.in提供输入数据。文件的第1 行有2 个正整数n和k,分别表示开区间的
个数和开区间的可重迭数。接下来的n行,每行有2个整数,表示开区间的两个端点坐标。
«结果输出:
程序运行结束时,将计算出的最长k可重区间集的长度输出到文件interv.out中。
输入文件示例 输出文件示例
interv.in
4 2
1 7
6 8
7 10

9 13

interv.out

15

/*
朴素的做法:
把k看作是k条路径,一条路径只能由不重复的区间组成,每个区间只能用一次,然后拆点跑最大费用流。
*/
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
#define N 1010
#define inf 1000000000
using namespace std;
int head[N],dis[N],inq[N],fa[N],n,k,S,T,cnt=;
struct Node{int l,r;}a[N];
struct node{int v,f,w,pre;}e[N*];
queue<int> q;
void add(int u,int v,int f,int w){
e[++cnt].v=v;e[cnt].f=f;e[cnt].w=w;e[cnt].pre=head[u];head[u]=cnt;
e[++cnt].v=u;e[cnt].f=;e[cnt].w=-w;e[cnt].pre=head[v];head[v]=cnt;
}
bool spfa(){
for(int i=;i<=T;i++) dis[i]=inf;
dis[S]=;q.push(S);
while(!q.empty()){
int u=q.front();q.pop();inq[u]=;
for(int i=head[u];i;i=e[i].pre)
if(e[i].f&&dis[e[i].v]>dis[u]+e[i].w){
dis[e[i].v]=dis[u]+e[i].w;
fa[e[i].v]=i;
if(!inq[e[i].v]){
inq[e[i].v]=;
q.push(e[i].v);
}
}
}
return dis[T]!=inf;
}
int updata(){
int i=fa[T],x=inf;
while(i){
x=min(x,e[i].f);
i=fa[e[i^].v];
}
i=fa[T];
while(i){
e[i].f-=x;
e[i^].f+=x;
i=fa[e[i^].v];
}
return x*dis[T];
}
bool cmp(const Node&x,const Node&y){
if(x.l==y.l) return x.r<y.r;
return x.l<y.l;
}
int main(){
freopen("interv.in","r",stdin);
freopen("interv.out","w",stdout);
scanf("%d%d",&n,&k);
for(int i=;i<=n;i++)
scanf("%d%d",&a[i].l,&a[i].r);
sort(a+,a+n+,cmp);
S=;T=n*+;int SS=n*+;
add(S,SS,k,);
for(int i=;i<=n;i++){
add(SS,i,inf,);
add(i+n,T,inf,);
add(i,i+n,,a[i].l-a[i].r);
}
for(int i=;i<=n;i++)
for(int j=i+;j<=n;j++)
if(a[i].r<=a[j].l) add(i+n,j,,);
int minv=;
while(spfa()) minv+=updata();
printf("%d",-minv);
return ;
}
/*
还有一种神奇的做法:
离散化所有区间的端点,把每个端点看做一个顶点,建立附加源S汇T。
建图如下:
从S到顶点1(最左边顶点)连接一条容量为K,费用为0的有向边。
从顶点2N(最右边顶点)到T连接一条容量为K,费用为0的有向边。
从顶点i到顶点i+1(i+1<=2N),连接一条容量为无穷大,费用为0的有向边。
对于每个区间[a,b],从a对应的顶点i到b对应的顶点j连接一条容量为1,费用为区间长度的有向边。
*/
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
#define N 1010
#define inf 1000000000
using namespace std;
int l[N],r[N],len[N],a[N],head[N],dis[N],inq[N],fa[N],n,k,S,T,cnt=;
struct node{int v,f,w,pre;}e[N*];
queue<int> q;
void add(int u,int v,int f,int w){
e[++cnt].v=v;e[cnt].f=f;e[cnt].w=w;e[cnt].pre=head[u];head[u]=cnt;
e[++cnt].v=u;e[cnt].f=;e[cnt].w=-w;e[cnt].pre=head[v];head[v]=cnt;
}
bool spfa(){
for(int i=;i<=T;i++) dis[i]=inf;
dis[S]=;q.push(S);
while(!q.empty()){
int u=q.front();q.pop();inq[u]=;
for(int i=head[u];i;i=e[i].pre)
if(e[i].f&&dis[e[i].v]>dis[u]+e[i].w){
dis[e[i].v]=dis[u]+e[i].w;
fa[e[i].v]=i;
if(!inq[e[i].v]){
inq[e[i].v]=;
q.push(e[i].v);
}
}
}
return dis[T]!=inf;
}
int updata(){
int i=fa[T],x=inf;
while(i){
x=min(x,e[i].f);
i=fa[e[i^].v];
}
i=fa[T];
while(i){
e[i].f-=x;
e[i^].f+=x;
i=fa[e[i^].v];
}
return x*dis[T];
}
int main(){
//freopen("interv.in","r",stdin);
//freopen("interv.out","w",stdout);
scanf("%d%d",&n,&k);
for(int i=;i<=n;i++){
scanf("%d%d",&l[i],&r[i]);
a[i*-]=l[i];a[i*]=r[i];len[i]=r[i]-l[i];
}
sort(a+,a+n*+);
for(int i=;i<=n;i++){
l[i]=lower_bound(a+,a+n*+,l[i])-a;
r[i]=lower_bound(a+,a+n*+,r[i])-a;
}
S=;T=n*+;
add(,,k,);add(n*,T,k,);
for(int i=;i<n*;i++) add(i,i+,inf,);
for(int i=;i<=n;i++) add(l[i],r[i],,-len[i]);
int minv=;
while(spfa()) minv+=updata();
printf("%d",-minv);
return ;
}

最长k可重区间集(cogs 743)的更多相关文章

  1. 【网络流24题】最长k可重区间集(费用流)

    [网络流24题]最长k可重区间集(费用流) 题面 Cogs Loj 洛谷 题解 首先注意一下 这道题目里面 在Cogs上直接做就行了 洛谷和Loj上需要判断数据合法,如果\(l>r\)就要交换\ ...

  2. COGS743. [网络流24题] 最长k可重区间集

    743. [网络流24题] 最长k可重区间集 ★★★   输入文件:interv.in   输出文件:interv.out   简单对比时间限制:1 s   内存限制:128 MB «问题描述: «编 ...

  3. 【网络流24题】No.21 (最长 k 可重区间集问题 最长不相交路径 最大费用流)

    [] 输入文件示例input.txt4 21 76 87 109 13 输出文件示例output.txt15 [分析] 直接co题解好了,写得挺全.. [建模方法] 方法1 按左端点排序所有区间,把每 ...

  4. (luogu P3358)最长k可重区间集问题 [TPLY]

    最长k可重区间集问题 题目链接 https://www.luogu.org/problemnew/show/3358 做法 所有点向下一个点连容量为k费用为0的边 l和r连容量为1费用为区间长度的边 ...

  5. 【网络流24题21】最长k可重区间集问题

    题面戳我 题目描述 对于给定的开区间集合I和正整数k,计算开区间集合I的最长k可重区间集的长度. 输入格式: 的第 1 行有 2 个正整数n和k,分别表示开区间的个数和开区间的可重迭数.接下来的 n行 ...

  6. 网络流 P3358 最长k可重区间集问题

    P3358 最长k可重区间集问题 题目描述 对于给定的开区间集合 I 和正整数 k,计算开区间集合 I 的最长 k可重区间集的长度. 输入输出格式 输入格式: 的第 1 行有 2 个正整数 n和 k, ...

  7. LibreOJ #6014. 「网络流 24 题」最长 k 可重区间集

    #6014. 「网络流 24 题」最长 k 可重区间集 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: 匿名 提交提交记录统计讨论测试数据   ...

  8. 【刷题】LOJ 6014 「网络流 24 题」最长 k 可重区间集

    题目描述 给定实直线 \(L\) 上 \(n\) 个开区间组成的集合 \(I\) ,和一个正整数 \(k\) ,试设计一个算法,从开区间集合 \(I\) 中选取出开区间集合 \(S \subseteq ...

  9. [网络流24题] 最长k可重区间集

    https://www.luogu.org/problemnew/show/3358 以区间(1,5),(2,6),(7,8)为例 建模方法一: 建模方法二: 离散化区间端点 相当于找k条费用最大的不 ...

随机推荐

  1. java基础面试题:抽象类中是否可以有静态的main方法?

  2. c++异常处理--创建自己的异常处理类

    复习了一下c++中的异常处理! 继承exception类 class myException : public std::exception { public: explicit myExceptio ...

  3. 该网页无法正常运作 目前无法处理此请求HTTP ERROR 500?

    由于php.ini配置文件中错误显示关闭导致. 将下值由Off 变更为 On display_errors = On display_startup_errors = On

  4. js中的日期

    创建日期对象: var date1 = new Date(2018, 11,10)  第二个参数传入的是月份,月份是0-11,实际上要加1 获得现在的时间:var date2 = Date.now() ...

  5. k8s的secret基本概念及案例

    secret相对于configMap,功能上是相似的但是secret是以其他编码方式去记录配置信息的,但是也可以被解读,只不过有技术门槛,不是那么容易就被解读.使用base64可以解码:echo ** ...

  6. DevOps - CI/CD - Jenkins

    Jenkins 是一款流行的开源持续集成(Continuous Integration)工具,广泛用于项目开发,具有自动化构建.测试和部署等功能.本文以 CentOS7 环境为例,总结了 Jenkin ...

  7. python 爬虫豆瓣top250

    网页api:https://movie.douban.com/top250?start=0&filter= 用到的模块:urllib,re,csv 捣鼓一上午终于好了,有些小问题 (top21 ...

  8. RDLC Reporting in Visual Studio 2017

    原文:RDLC Reporting in Visual Studio 2017 Visual Studio 2017 中可以使用 RDLC Reporting 插件来设计报表,SAP Crystal ...

  9. windows下虚拟环境中配置MySQL-python错误问题

    下载mysql 下载mysql-python 这两步基本没有问题怪就怪的 MySQL-python-1.2.3.win-amd64-py2.7 文件只能安装到python27  路径下 然后在虚拟环境 ...

  10. 设计模式之第17章-备忘录模式(Java实现)

    设计模式之第17章-备忘录模式(Java实现) 好男人就是我,我就是曾小贤.最近陈赫和张子萱事件闹得那是一个沸沸扬扬.想想曾经每年都有爱情公寓陪伴的我现如今过年没有了爱情公寓总是感觉缺少点什么.不知道 ...