最长 k 可重区间集问题题解:

突然想起这个锅还没补,于是来把这里补一下qwq。

1.题意简述:

有\(n\)个开区间,这\(n\)个开区间组成了一个直线\(L\),要求选择一些区间,使得在直线\(L\)上的任意一点,对于你选择的区间来说,包含这个点的区间个数不超过$k $,且满足区间长度和最大。

2.要点:

  • 因为是开区间,所以长度为\(r-l\)

  • 所用算法为\(EK\)费用流

3.\(solution1 :\)

首先让我们思考这个过程,我们要选择一些区间,那么限制条件是得给在区间上的。考虑这么一种情况,就是有两个区间互不相交。

这种情况对这两个区间互相之间是不影响的,也就是说这两个区间是可以一起选的。换成网络流考虑,这两个区间是可以连边的。

然后考虑怎么连边,我们发现这道题的连边极其复杂,我们要考虑这些区间的长度,也就是每个区间对应的权值。

如果这个当为点权的话是不好计算的,那么我们就尝试拆点,把区间给拆开,然后把点权当成边权来计算。

照样是将一个点\(x\)拆成入点\(x\)和出点\(x+N\)因为一个区间只能选择\(1\)次,那么,我们给每个点对应的入点和出点之间连接一条流量为1,费用为区间长度的边。这样我们就完成了对与区间点权的转化,把他转化成了边权。

那么我们说到,像上图中那样是可以同时选的,因为这两个点之间不影响,但是具体选不选呢?这得看后面不选这个是否更优。于是,只要满足这两个区间之间没有交,这两个区间之内就可以连边。

然后就是考虑对于每个点只能被\(k\)个点覆盖这个限制,这个限制怎么办?这个限制换一种说法,永远不会选择\(k\)个以上交于一点的区间。每个点被覆盖当且仅当线段的起点或者说是终点被覆盖。

我们把区间抽象成立一条条线段。

然后按着线段的集合进行分层,每一层中的线段是互不相交的

那么最多只能叠上\(k\)层,为什么呢?因为每一层中线段是互不相交的,那么后一层一定与前面的线段有相交。然后找到第\(k\)层的时候,得到的收益一定最大。

那么就对于跑\(k\)次的限制来吧,可以在加一个附加源点进行限流,设定流量为\(k\),然后用这个点去和每个入点进行连接。这样为什么是对的呢?因为,你发现一件事,你之前连的边之中就是连接的互不相交的边,那么这么来,对于每一个点来说,你就是一层,然后当你跑完后,那么得到的答案即为最大。

(思路有点乱,建议自己理理

那么建模是这样的:

  1. 建立一个超级源点\(s\),在建立一颗附加源点\(S\),中间连费用为\(0\),流量为\(k\)的边。
  2. 附加源点\(S\)向每一个入点连一条流量为\(1\),费用为\(0\)的边
  3. 每个入点向自己的出点连一条流量为\(1\),费用为区间长度的边
  4. 对于每一个区间,找到一个与它不重的区间,他们之间连一条流量为\(INF\),费用为\(0\)的边。
  5. 建立一个超级汇点\(t\),每一个出点向超级汇点连接一条流量为\(1\),费用为\(0\)的边。

代码:

  1. #include<bits/stdc++.h>
  2. #define int long long
  3. using namespace std;
  4. template<typename T> inline void read(T &x){
  5. T f=1;x=0;
  6. char ch=getchar();
  7. while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
  8. while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
  9. x*=f;
  10. }
  11. const int N = 4e5,INF=2e9;
  12. int n,k;
  13. struct query{
  14. int l,r;
  15. }a[N];
  16. bool cmp(query x,query y){
  17. return x.l<y.l;
  18. }
  19. int nex[N],first[N],v[N],num=1,flow[N],cost[N],pre[N];
  20. void add(int from,int to,int val,int c){
  21. nex[++num]=first[from];
  22. first[from]=num;
  23. v[num]=to;
  24. flow[num]=val;
  25. cost[num]=c;
  26. }
  27. int dis[N],vis[N],inf[N],q[N],last[N],mincost;
  28. bool spfa(int s,int t){
  29. memset(dis,0xcf,sizeof(dis));
  30. memset(vis,0,sizeof(vis));
  31. memset(inf,0x7f,sizeof(inf));
  32. q[1]=s;
  33. vis[s]=1;
  34. dis[s]=0;
  35. pre[t]=-1;
  36. int l=0,r=1;
  37. while(l!=r){
  38. int u=q[++l];
  39. vis[u]=0;
  40. for(int i=first[u];i;i=nex[i]){
  41. int to=v[i];
  42. if(flow[i] && dis[to]<dis[u]+cost[i]){
  43. dis[to]=dis[u]+cost[i];
  44. pre[to]=u;
  45. last[to]=i;
  46. inf[to]=min(inf[u],flow[i]);
  47. if(!vis[to]){
  48. vis[to]=1;
  49. q[++r]=to;
  50. }
  51. }
  52. }
  53. }
  54. return pre[t]!=-1;
  55. }
  56. void EK(int s,int t){
  57. while(spfa(s,t)){
  58. int now=t;
  59. mincost+=inf[t]*dis[t];
  60. while(now!=s){
  61. flow[last[now]]-=inf[t];
  62. flow[last[now]^1]+=inf[t];
  63. now=pre[now];
  64. }
  65. }
  66. }
  67. int s,t,S;
  68. signed main(){
  69. read(n),read(k);
  70. for(int i=1;i<=n;i++){
  71. read(a[i].l),read(a[i].r);
  72. if(a[i].l>a[i].r) swap(a[i].l,a[i].r);
  73. }
  74. s=0;
  75. S=4*n;
  76. t=5*n;
  77. add(s,S,k,0);
  78. add(S,s,0,0);
  79. sort(a+1,a+n+1,cmp);
  80. for(int i=1;i<=n;i++){
  81. add(S,i,1,0);
  82. add(i,S,0,0);
  83. add(i,i+n,1,a[i].r-a[i].l);
  84. add(i+n,i,0,a[i].l-a[i].r);
  85. add(i+n,t,1,0);
  86. add(t,i+n,0,0);
  87. }
  88. for(int i=1;i<=n;i++){
  89. for(int j=i+1;j<=n;j++){
  90. if(a[j].l>=a[i].r||a[i].l>=a[j].r){
  91. add(i+n,j,INF,0);
  92. add(j,i+n,0,0);
  93. }
  94. }
  95. }
  96. EK(s,t);
  97. cout<<mincost;
  98. return 0;
  99. }

4.$solution2:\ $

这里有网上的另一种做法,效果更加优异,但是我觉得怪怪的,反正我是没有直接想出来。但是这种做法的复杂度更优,我有空再补把。

这里把几篇讲得看起来很详细得题解拿过来,如果想学习得去看这个把。

1号大佬博客

2号大佬博客

花姐姐的博客

太难为我了,完结了QAQ。

网络流24题:最长 k 可重区间集问题题解的更多相关文章

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

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

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

    最长 \(k\) 可重区间集 题目大意 给定实心直线 \(L\) 上 \(n\) 个开区间组成的集合 \(I\) ,和一个正整数 \(k\) ,试设计一个算法,从开区间集合 \(I\) 中选取开区间集 ...

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

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

  4. [网络流24题] 最长K可重区间集问题

    题目链接:戳我 当时刷24题的时候偷了懒,没有写完,结果落下这道题没有写qwq结果今天考试T3中就有一部分要用到这个思想,蒟蒻我硬是没有想到网络流呜呜呜 最大费用流. 就是我们考虑将问题转化一下,转化 ...

  5. [网络流24题] 最长k可重区间集问题 (费用流)

    洛谷传送门 LOJ传送门 很巧妙的建图啊...刚了$1h$也没想出来,最后看的题解 发现这道题并不类似于我们平时做的网络流题,它是在序列上的,且很难建出来二分图的形. 那就让它在序列上待着吧= = 对 ...

  6. [网络流24题]最长k可重线段集[题解]

    最长 \(k\) 可重线段集 题目大意 给定平面 \(x-O-y\) 上 \(n\) 个开线段组成的集合 \(I\) ,和一个正整数 \(k\) .试设计一个算法,从开线段集合 \(I\) 中选取开线 ...

  7. [网络流24题] 最长k可重线段集问题 (费用流)

    洛谷传送门 LOJ传送门 最长k可重区间集问题的加强版 大体思路都一样的,不再赘述,但有一些细节需要注意 首先,坐标有负数,而且需要开$longlong$算距离 但下面才是重点: 我们把问题放到了二维 ...

  8. 网络流24题-最长k可重线段集问题

    最长k可重线段集问题 时空限制1000ms / 128MB 题目描述 给定平面 x−O−y 上 n 个开线段组成的集合 I,和一个正整数 k .试设计一个算法,从开线段集合 I 中选取出开线段集合 S ...

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

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

随机推荐

  1. Go语言流程控制03--goto跳转到任意标签位置

    package main import ( "fmt" "time" ) func main() { STUDYHARD: fmt.Println(" ...

  2. 转载 | Scala 如何避免使用 Null

    在 Java 里,null 是一个关键字,不是一个对象,所以对它调用任何方法都是非法的. Scala 的 Option类型 Scala在变量和函数返回值可能不会引用任何值的时候使用 Option 类型 ...

  3. 原子层沉积(ALD)和化学气相沉积(CVD)微电子制造铜金属化的研究进展

    原子层沉积(ALD)和化学气相沉积(CVD)微电子制造铜金属化的研究进展 Atomic Layer Deposition (ALD) and Chemical Vapor Deposition (CV ...

  4. 打造住院新体验,GVS智慧病房有何独到之处?

    3月26-28日,由广东省医院协会主办的"2021第二届广东省医院建设大会暨医院建筑与装备展览会"在广州琶洲国际采购中心盛大举办,来自全国各地的医院代表及企事业单位代表4000余人 ...

  5. 10分钟用JS实现微信 "炸屎"大作战

    大家好,我是秋风,近日,微信又发布了新功能(更新到微信8.0.6).最火热的非"炸屎"功能莫属了,各种群里纷纷玩起了炸屎的功能. 不知道大家是否经历过那样一个时候,小时候(我是说很 ...

  6. 【工具解析】瑞士军刀bettercap2.X解析_第一期_编写HTTP代理注入模块_http(s).proxy.script

    /文章作者:Kali_MG1937 CNBLOG博客号:ALDYS4 QQ:3496925334/ 前言 bettercap已经从1.6更新至2.0版本 语言也从ruby改为了go 编写注入模块指定的 ...

  7. 【Android编程】Java利用Socket类编写Metasploit安卓载荷辅助模块

    /作者:Kali_MG1937 CSDN博客:ALDYS4 QQ:3496925334/ 注意!此文章被作者标记到 黑历史 专栏中,这意味着本篇文章可能存在 质量低下,流水账文,笔法低质 的问题 为了 ...

  8. InnoDB 静态数据加密的常见问题合集

    1. 数据是否为有权查看数据的用户解密? 是的.InnoDB静态数据加密旨在透明地在数据库中应用加密,而不会影响现有应用程序.以加密格式返回数据会破坏大多数现有应用程序. InnoDB静态数据加密提供 ...

  9. 【NX二次开发】创建有界平面UF_MODL_create_bplane

    先准备几条曲线如下图所示,我们用这几条线来创建一个有界平面: 效果:  源码: //有界平面 extern DllExport void ufusr(char *param, int *returnC ...

  10. 有效Ajax案例

    <script>$(document).ready(function(){ $("input:submit").click(function(){ $.ajax({ t ...