【网络流24题】No.21 (最长 k 可重区间集问题 最长不相交路径 最大费用流)
【】
输入文件示例
input.txt
4 2
1 7
6 8
7 10
9 13输出文件示例
output.txt
15
【分析】
直接co题解好了,写得挺全。。
【建模方法】
方法1
按左端点排序所有区间,把每个区间拆分看做两个顶点<i.a><i.b>,建立附加源S汇T,以及附加顶点S’。
1、连接S到S’一条容量为K,费用为0的有向边。
2、从S’到每个<i.a>连接一条容量为1,费用为0的有向边。
3、从每个<i.b>到T连接一条容量为1,费用为0的有向边。
4、从每个顶点<i.a>到<i.b>连接一条容量为1,费用为区间长度的有向边。
5、对于每个区间i,与它右边的不相交的所有区间j各连一条容量为1,费用为0的有向边。求最大费用最大流,最大费用流值就是最长k可重区间集的长度。
方法2
离散化所有区间的端点,把每个端点看做一个顶点,建立附加源S汇T。
1、从S到顶点1(最左边顶点)连接一条容量为K,费用为0的有向边。
2、从顶点2N(最右边顶点)到T连接一条容量为K,费用为0的有向边。
3、从顶点i到顶点i+1(i+1<=2N),连接一条容量为无穷大,费用为0的有向边。
4、对于每个区间[a,b],从a对应的顶点i到b对应的顶点j连接一条容量为1,费用为区间长度的有向边。求最大费用最大流,最大费用流值就是最长k可重区间集的长度。
【建模分析】
这个问题可以看做是求K条权之和最大的不想交路径,每条路径为一些不相交的区间序列。由于是最大费用流,两条路径之间一定有一些区间相交,可以看做事相交部分重复了2次,而K条路经就是最多重复了K次。最简单的想法就是把区间排序后,不相交的区间之间连接一条边,由于每个区间只能用一次,所以要拆点,点内限制流量。如果我们改变一下思路,把端点作为网络中的顶点,区间恰恰是特定一些端点之间的边,这样建模的复杂度更小。方法1的边数是O(N^2)的,而方法2的边数是O(N)的,可以解决更大规模的问题。
感觉我的数据错了hhh
- #include<cstdio>
- #include<cstdlib>
- #include<cstring>
- #include<iostream>
- #include<algorithm>
- #include<queue>
- #include<cmath>
- using namespace std;
- #define Maxn 101000
- #define INF 0xfffffff
- struct node
- {
- int x,y,f,o,c,next;
- }t[Maxn*];int len;
- int first[Maxn];
- int mymin(int x,int y) {return x<y?x:y;}
- int mymax(int x,int y) {return x>y?x:y;}
- void ins(int x,int y,int f,int c)
- {
- t[++len].x=x;t[len].y=y;t[len].f=f;t[len].c=c;
- t[len].next=first[x];first[x]=len;t[len].o=len+;
- t[++len].x=y;t[len].y=x;t[len].f=;t[len].c=-c;
- t[len].next=first[y];first[y]=len;t[len].o=len-;
- }
- int st,ed;
- queue<int > q;
- int dis[Maxn],pre[Maxn],flow[Maxn];
- bool inq[Maxn];
- bool bfs()
- {
- while(!q.empty()) q.pop();
- // memset(dis,-1,sizeof(dis));
- for(int i=;i<=ed;i++) dis[i]=-INF;
- memset(inq,,sizeof(inq));
- q.push(st);dis[st]=;flow[st]=INF;inq[st]=;
- while(!q.empty())
- {
- int x=q.front();
- for(int i=first[x];i;i=t[i].next) if(t[i].f>)
- {
- int y=t[i].y;
- if(dis[y]<dis[x]+t[i].c)
- {
- dis[y]=dis[x]+t[i].c;
- pre[y]=i;
- flow[y]=mymin(flow[x],t[i].f);
- if(!inq[y])
- {
- inq[y]=;
- q.push(y);
- }
- }
- }
- inq[x]=;q.pop();
- }
- if(dis[ed]>-INF) return ;
- return ;
- }
- void output()
- {
- for(int i=;i<=len;i+=)
- printf("%d->%d %d %d\n",t[i].x,t[i].y,t[i].f,t[i].c);
- printf("\n");
- }
- int max_flow()
- {
- int ans=,sum=;
- while(bfs())
- {
- sum+=dis[ed]*flow[ed];
- ans+=flow[ed];
- int now=ed;
- while(now!=st)
- {
- t[pre[now]].f-=flow[ed];
- t[t[pre[now]].o].f+=flow[ed];
- now=t[pre[now]].x;
- }
- }
- return sum;
- }
- struct hp
- {
- int x,id;
- }tt[Maxn];int tl=;
- int nx[Maxn],ny[Maxn],ln[Maxn];
- bool cmp(hp x,hp y) {return x.x<y.x;}
- void init()
- {
- int n,k;
- scanf("%d%d",&n,&k);
- len=;
- memset(first,,sizeof(first));
- int mx=;
- for(int i=;i<=n;i++)
- {
- int x,y;
- // scanf("%d%d",&x,&y);
- // ins(x,y,1,y-x);
- scanf("%d%d",&nx[i],&ny[i]);
- ln[i]=ny[i]-nx[i];
- tt[++tl].x=nx[i];tt[tl].id=i;
- tt[++tl].x=ny[i];tt[tl].id=i+n;
- // mx=mymax(mx,y);
- }
- sort(tt+,tt++tl,cmp);
- int pp=;
- int now=tt[].x;tt[].x=;
- for(int i=;i<=tl;i++)
- {
- if(tt[i].x!=now) pp++,now=tt[i].x;
- tt[i].x=pp;
- }
- for(int i=;i<=tl;i++)
- {
- if(tt[i].id>n) ny[tt[i].id-n]=tt[i].x;
- else nx[tt[i].id]=tt[i].x;
- }
- for(int i=;i<=n;i++) ins(nx[i],ny[i],,ln[i]);
- mx=pp;
- st=mx+;ed=st+;
- ins(st,,k,);
- for(int i=;i<mx;i++) ins(i,i+,k,);
- ins(mx,ed,k,);
- }
- int main()
- {
- init();
- // output();
- int ans;
- ans=max_flow();
- printf("%d\n",ans);
- return ;
- }
2016-11-08 07:26:58
【网络流24题】No.21 (最长 k 可重区间集问题 最长不相交路径 最大费用流)的更多相关文章
- 最长k可重区间集问题&&最长k可重线段集问题
题解: 洛谷上这两题的题意都是有问题的 按照标程题意不应该是开区间而是左开右闭区间 然后连边比较巧妙 我们可以看成选k条不相交的路径,其中i-i+1中有k条边 所以建图i-i+1流量为k,权值为0 l ...
- 【网络流24题21】最长k可重区间集问题
题面戳我 题目描述 对于给定的开区间集合I和正整数k,计算开区间集合I的最长k可重区间集的长度. 输入格式: 的第 1 行有 2 个正整数n和k,分别表示开区间的个数和开区间的可重迭数.接下来的 n行 ...
- COGS743. [网络流24题] 最长k可重区间集
743. [网络流24题] 最长k可重区间集 ★★★ 输入文件:interv.in 输出文件:interv.out 简单对比时间限制:1 s 内存限制:128 MB «问题描述: «编 ...
- 【网络流24题】最长k可重区间集(费用流)
[网络流24题]最长k可重区间集(费用流) 题面 Cogs Loj 洛谷 题解 首先注意一下 这道题目里面 在Cogs上直接做就行了 洛谷和Loj上需要判断数据合法,如果\(l>r\)就要交换\ ...
- LibreOJ #6014. 「网络流 24 题」最长 k 可重区间集
#6014. 「网络流 24 题」最长 k 可重区间集 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: 匿名 提交提交记录统计讨论测试数据 ...
- loj #6014. 「网络流 24 题」最长 k 可重区间集
#6014. 「网络流 24 题」最长 k 可重区间集 题目描述 给定实直线 L LL 上 n nn 个开区间组成的集合 I II,和一个正整数 k kk,试设计一个算法,从开区间集合 I II 中选 ...
- 【网络流24题】最长k可重区间集问题(费用流)
[网络流24题]最长k可重区间集问题 [问题分析] 最大权不相交路径问题,可以用最大费用最大流解决. [建模方法] 方法1 按左端点排序所有区间,把每个区间拆分看做两个顶点<i.a>< ...
- [网络流24题]最长k可重区间集[题解]
最长 \(k\) 可重区间集 题目大意 给定实心直线 \(L\) 上 \(n\) 个开区间组成的集合 \(I\) ,和一个正整数 \(k\) ,试设计一个算法,从开区间集合 \(I\) 中选取开区间集 ...
- 网络流24题:最长 k 可重区间集问题题解
最长 k 可重区间集问题题解: 突然想起这个锅还没补,于是来把这里补一下qwq. 1.题意简述: 有\(n\)个开区间,这\(n\)个开区间组成了一个直线\(L\),要求选择一些区间,使得在直线\(L ...
随机推荐
- Redis与Memcached对比
Redis是一种高级key-value数据库.它跟memcached类似,不过数据可以持久化,而且支持的数据类型很丰富,有字符串.链表.集合和有序集合.支持在服务器端计算集合的并,交和补集等.还支持多 ...
- 【转】性能测试设计和LR原理的探讨
做了4个迭代的性能测试, 在没有需求的情况下步步艰辛,把代码和框架独立开发从0到一万多行代码的测试工具(脚本),作为性能测试工具佼佼者Lr,我时而拿他作参考,山寨了它很多 东西,同时带有很多疑问对它实 ...
- php生成验证码图片
0:效果图 1:index.php用来生成验证码图片 <?php session_start(); header ('Content-Type: image/png'); $image=imag ...
- Unity3D 之2D动画机
这里来讲解一下2D动画机的使用 2D的时候,默认的情况下,可以调用默认的站立之类的动画,然后通过触发,可以变化自己的动画. 一:将一个图切成一些一个元素 二:创建一个精灵,给精灵添加一个动画机 三:给 ...
- UNIX线程之间的关系
我们在一个线程中经常会创建另外的新线程,如果主线程退出,会不会影响它所创建的新线程呢?下面就来讨论一下. 1. 主线程等待新线程先结束退出,主线程后退出.正常执行. 示例代码: #include & ...
- Web电子商务网(三层)V2.0源码
Web电子商务网(三层)V2.0源码 源码描述: 一.源码特点 采用三层架构开发,购物车功能 二.功能介绍 前台集成了产品在线展示,用户注册.在线调查.在线投稿 后台有类别管理\图书管理\订单 ...
- android studio安装后卡在fetching Android sdk compoment information
解决办法: 找到android studio 安装目录下bin目录中(D:\Android\Android Studio\bin)的idea.properties文件,在文件末尾处添加disable. ...
- Codevs 1198 国王游戏 2012年NOIP全国联赛提高组
1198 国王游戏 2012年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description 恰逢 H 国国庆,国王邀 ...
- Codevs 1066 引水入城 2010年NOIP全国联赛提高组
1066 引水入城 2010年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 传送门 题目描述 Description 在一个遥远的国度 ...
- mysql学习笔记2
drop database 数据库名称;————删除数据库 show columns from 数据表名[from 数据库名]:(或者 show columns from 数据库.数据表名:)———— ...