P3358 最长k可重区间集问题

题目描述

对于给定的开区间集合 I 和正整数 k,计算开区间集合 I 的最长 k可重区间集的长度。

输入输出格式

输入格式:

的第 1 行有 2 个正整数 n和 k,分别表示开区间的个数和开区间的可重迭数。接下来的 n行,每行有 2 个整数,表示开区间的左右端点坐标。

输出格式:

将计算出的最长 k可重区间集的长度输出

输入输出样例

输入样例#1: 复制

  1. 4 2
  2. 1 7
  3. 6 8
  4. 7 10
  5. 9 13
输出样例#1: 复制

  1. 15

说明

对于100%的数据,1\le n\le 5001≤n≤500,1\le k\le 31≤k≤3

写一下这个题目的思路,这个图很难建。
看了一下题解,觉得很巧妙。

看了这个图就好理解一点了,就是你要把k假定为网络流的最大流量,把每一个区间离散化。

这个看代码更好理解一些,不过可以抽象的讲一下。

就是你把这些区间互不相重叠的划成一条路,假设有5条路,k=2,

那么最多只能从这五条路里面选择两条路,因为如果大于等于2,那么就会出现问题,比如说,第一个区间和第二个区间,

则第二个区间里的每一段,如果不是和第一个区间肯定都是和第一个区间的某一段有交集。

。。。。不好说,还是看代码吧,多搜搜题解,不放弃,最后总会写的。

  1. #include <cstdio>
  2. #include <cstdlib>
  3. #include <queue>
  4. #include <vector>
  5. #include <iostream>
  6. #include <algorithm>
  7. #include <map>
  8. #include <cstring>
  9. #include <string>
  10. #define inf 0x3f3f3f3f
  11. using namespace std;
  12. typedef long long ll;
  13. const int INF = 0x3f3f3f3f;
  14. const int maxn = 1e5;
  15. struct edge
  16. {
  17. int u, v, c, f, cost;
  18. edge(int u, int v, int c, int f, int cost) :u(u), v(v), c(c), f(f), cost(cost) {}
  19. };
  20. vector<edge>e;
  21. vector<int>G[maxn];
  22. int a[maxn];//找增广路每个点的水流量
  23. int p[maxn];//每次找增广路反向记录路径
  24. int d[maxn];//SPFA算法的最短路
  25. int inq[maxn];//SPFA算法是否在队列中
  26. int s, t;
  27. void init(int n)
  28. {
  29. for (int i = ; i <= n; i++)G[i].clear();
  30. e.clear();
  31. }
  32. void add(int u, int v, int c, int cost)
  33. {
  34. e.push_back(edge(u, v, c, , cost));
  35. e.push_back(edge(v, u, , , -cost));
  36. int m = e.size();
  37. G[u].push_back(m - );
  38. G[v].push_back(m - );
  39. }
  40. bool bellman(int s, int t, int& flow, long long & cost)
  41. {
  42. memset(d, 0xef, sizeof(d));
  43. memset(inq, , sizeof(inq));
  44. d[s] = ; inq[s] = ;//源点s的距离设为0,标记入队
  45. p[s] = ; a[s] = INF;//源点流量为INF(和之前的最大流算法是一样的)
  46.  
  47. queue<int>q;//Bellman算法和增广路算法同步进行,沿着最短路拓展增广路,得出的解一定是最小费用最大流
  48. q.push(s);
  49. while (!q.empty())
  50. {
  51. int u = q.front();
  52. q.pop();
  53. inq[u] = ;//入队列标记删除
  54. for (int i = ; i < G[u].size(); i++)
  55. {
  56. edge & now = e[G[u][i]];
  57. int v = now.v;
  58. if (now.c > now.f && d[v] < d[u] + now.cost)
  59. //now.c > now.f表示这条路还未流满(和最大流一样)
  60. //d[v] > d[u] + e.cost Bellman 算法中边的松弛
  61. {
  62. d[v] = d[u] + now.cost;//Bellman 算法边的松弛
  63. p[v] = G[u][i];//反向记录边的编号
  64. a[v] = min(a[u], now.c - now.f);//到达v点的水量取决于边剩余的容量和u点的水量
  65. if (!inq[v]) { q.push(v); inq[v] = ; }//Bellman 算法入队
  66. }
  67. }
  68. }
  69. if (d[t] < )return false;//找不到增广路
  70. flow += a[t];//最大流的值,此函数引用flow这个值,最后可以直接求出flow
  71. cost += (long long)d[t] * (long long)a[t];//距离乘上到达汇点的流量就是费用
  72. for (int u = t; u != s; u = e[p[u]].u)//逆向存边
  73. {
  74. e[p[u]].f += a[t];//正向边加上流量
  75. e[p[u] ^ ].f -= a[t];//反向边减去流量 (和增广路算法一样)
  76. }
  77. return true;
  78. }
  79. int MaxcostMaxflow(int s, int t, long long & cost)
  80. {
  81. cost = ;
  82. int flow = ;
  83. while (bellman(s, t, flow, cost));//由于Bellman函数用的是引用,所以只要一直调用就可以求出flow和cost
  84. return flow;//返回最大流,cost引用可以直接返回最小费用
  85. }
  86.  
  87. struct node
  88. {
  89. int l, r;
  90. }exa[maxn];
  91. bool cmp(node a,node b)
  92. {
  93. return a.l < b.l;
  94. }
  95. int main()
  96. {
  97. int n, m;
  98. cin >> n >> m;
  99. int s1 = ;
  100. s = , t = * n + ;
  101. for(int i=;i<=n;i++)
  102. {
  103. cin >> exa[i].l >> exa[i].r;
  104. if (exa[i].l > exa[i].r) swap(exa[i].l, exa[i].r);
  105. }
  106. sort(exa + , exa + + n, cmp);
  107. add(s, s1, m, );
  108. for(int i=;i<=n;i++)
  109. {
  110. add(s1, + * i - , , );
  111. add( + * i - , + * i,, exa[i].r - exa[i].l);
  112. add( + * i, t, , );
  113. for(int j=;j<i;j++)
  114. {
  115. if (exa[j].r <= exa[i].l) add( + * j, + * i - , , );
  116. }
  117. }
  118. ll cost = ;
  119. int ans = MaxcostMaxflow(s, t, cost);
  120. printf("%lld\n", cost);
  121. return ;
  122. }

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

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

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

  2. 洛谷P3358 最长k可重区间集问题(费用流)

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

  3. 洛谷P3358 最长k可重区间集问题(费用流)

    传送门 因为一个zz错误调了一个早上……汇点写错了……spfa也写错了……好吧好像是两个…… 把数轴上的每一个点向它右边的点连一条边,容量为$k$,费用为$0$,然后把每一个区间的左端点向右端点连边, ...

  4. luogu P3358 最长k可重区间集问题

    网络流建图好难,这题居然是网络流(雾,一般分析来说,有限制的情况最大流情况可以拆点通过capacity来限制,比如只使用一次,把一个点拆成入点出点,capacity为1即可,这题是限制最大k重复,可以 ...

  5. P3358 最长k可重区间集问题

    题目链接 \(Click\) \(Here\) 这题的写法非常巧妙. 每个位置的点向它的下一个位置连一个容量为\(INF\)的边,从区间的左端点往右端点拉一条容量为\(1\),费用为区间长度的边,从起 ...

  6. 【Luogu】P3358最长k可重区间集问题(费用流)

    题目链接 这题费用瘤,数据貌似还是错的. 把线段抽象抽象拆成两个点,入点表示左端,出点表示右端,连上容量为1费用-长度的边. 不相交线段随便连下,源点向拆出的原点S'连费用为0容量k,然后跑费用流. ...

  7. 洛谷 P3358 最长k可重区间集问题 【最大费用最大流】

    同 poj 3680 https:www.cnblogs.com/lokiii/p/8413139.html #include<iostream> #include<cstdio&g ...

  8. 「网络流24题」「LuoguP3358」 最长k可重区间集问题(费用流

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

  9. 最长k可重区间集

      P3358 最长k可重区间集问题 P3357 最长k可重线段集问题 P3356 火星探险问题 P4012 深海机器人问题 P3355 骑士共存问题 P2754 [CTSC1999]家园 题目描述 ...

随机推荐

  1. 并发容器之CopyOnWriteArraySet

    CopyOnWriteArraySet是基于CopyOnWriteArrayList实现的,其唯一的不同是在add时调用的是CopyOnWriteArrayList的addIfAbsent方法. 具体 ...

  2. SSM-SpringMVC-25:SpringMVC异常顶级之自定义异常解析器

    ------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥------------- 上篇博客相信大家也看到了,自定义异常,用了SimpleMappingExceptionResolver这个解析 ...

  3. OAthe2 Login use OkHttpClient and OAuth2RestTemplate

    http://samchu.logdown.com/posts/1437422-oathe2-login-use-okhttpclient-and-oauth2resttemplate?utm_sou ...

  4. 一次故障解决过程梳理:mysql varchar text timestamp

    CHAR 类型的一个变体是 VARCHAR 类型,char(M),M是指字节长度,和varchar(M)一样 故障原因:mysql主键设置为int(9),但数据量已经大于int(9)的范围了 tips ...

  5. checkbox事件的变化

    <input type="checkbox" checked={this.state.checked} onChange={this.checkedChangeHandler ...

  6. Hexo博客搭建

    http://www.jianshu.com/p/e99ed60390a8 http://blog.csdn.net/xuezhisdc/article/details/53130328 注意点: 1 ...

  7. 两个标签页定位第二个标签页元素时显示element not visible

    问题描述 web页面有两个标签页, 当转换到第二个标签页定位元素时, 显示element not visible. 代码 ... //省略 WebElement ele= browser.getEle ...

  8. Mave手动安装jar包

    今天配置Maven项目时有一个相应的jdbc驱动jar包导不进去,就自己导入了. 首先在官网上下载该jar包,地址为http://mvnrepository.com/ 点击jar下载. 用maven命 ...

  9. B20J_2836_魔法树_树链剖分+线段树

    B20J_2836_魔法树_树链剖分+线段树 题意: 果树共有N个节点,其中节点0是根节点,每个节点u的父亲记为fa[u].初始时,这个果树的每个节点上都没有果子(即0个果子). Add u v d ...

  10. 解决linux netcore https请求使用自签名证书忽略安全检查方法

    当前系统环境:centos7 x64. dotnet 2.0. 不管是 ServicePointManager.ServerCertificateValidationCallback = (a, b, ...