P3357 最长k可重线段集问题

题目描述

给定平面 x-O-yx−O−y 上 nn 个开线段组成的集合 II,和一个正整数 kk 。试设计一个算法,从开线段集合 II 中选取出开线段集合 S\subseteq IS⊆I ,使得在 xx 轴上的任何一点 pp,SS 中与直线 x=px=p 相交的开线段个数不超过 kk,且\sum\limits_{z\in S}|z|z∈S∑​∣z∣达到最大。这样的集合 SS 称为开线段集合 II 的最长 kk 可重线段集。\sum\limits_{z\in S}|z|z∈S∑​∣z∣ 称为最长 kk 可重线段集的长度。

对于任何开线段 zz,设其断点坐标为 (x_0,y_0)(x0​,y0​) 和 (x_1,y_1)(x1​,y1​),则开线段 zz 的长度 |z|∣z∣ 定义为:|z|=\lfloor\sqrt{(x_1-x_0)^2+(y_1-y_0)^2}\rfloor∣z∣=⌊(⌋

对于给定的开线段集合 II 和正整数 kk,计算开线段集合 II 的最长 kk 可重线段集的长度。

输入输出格式

输入格式:

文件的第一 行有 22 个正整数 nn 和 kk,分别表示开线段的个数和开线段的可重叠数。

接下来的 nn 行,每行有 44 个整数,表示开线段的 22 个端点坐标。

输出格式:

程序运行结束时,输出计算出的最长 kk 可重线段集的长度。

输入输出样例

输入样例#1: 复制

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

  1. 17

说明

1\leq n\leq5001≤n≤500

1 \leq k \leq 131≤k≤13

这个题目和之前的最长k可重区间集问题是一样的,就是把平面上的线段投影到x轴,但是呢,有一个点有问题,就是要

特判两条直线重合且垂直于x轴的这一种情况,具体是为什么呢,我也有点不明白为什么了,好像是会出现环的情况。

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

P3357 最长k可重线段集问题 网络流的更多相关文章

  1. 洛谷P3357 最长k可重线段集问题(费用流)

    传送门 其实和最长k可重区间集问题差不多诶…… 把这条开线段给压成x轴上的一条线段,然后按上面说的那种方法做即可 然而有一个坑点是线段可以垂直于x轴,然后一压变成一个点,连上正权环,求最长路……然后s ...

  2. 洛谷P3357 最长k可重线段集问题(费用流)

    题目描述 给定平面 x-O-yx−O−y 上 nn 个开线段组成的集合 II ,和一个正整数 kk .试设计一个算法,从开线段集合 II 中选取出开线段集合 S\subseteq IS⊆I ,使得在  ...

  3. 洛谷 P3357 最长k可重线段集问题【最大流】

    pre:http://www.cnblogs.com/lokiii/p/8435499.html 和最长k可重区间集问题差不多,也就是价值的计算方法不一样,但是注意这里可能会有x0==x1的情况也就是 ...

  4. luogu P3357 最长k可重线段集问题

    这题和3358一模一样,建模形式直接不用变,就两点不一样,一是len变化了,加入y后再更新即可,还有就是可能会出现x0=x1的情况,即一条开线段垂直x轴,如果我们依旧按照上一题的建图方法,就会出现负权 ...

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

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

  6. 【网络流24题】最长k可重线段集(费用流)

    [网络流24题]最长k可重线段集(费用流) 题面 Cogs的数据有问题 Loj 洛谷 题解 这道题和最长k可重区间集没有区别 只不过费用额外计算一下 但是,还是有一点要注意的地方 这里可以是一条垂直的 ...

  7. 【刷题】LOJ 6227 「网络流 24 题」最长k可重线段集问题

    题目描述 给定平面 \(\text{xoy}\) 上 \(n\) 个开线段组成的集合 \(\text{I}\) ,和一个正整数 \(k\) ,试设计一个算法. 从开线段集合 \(\text{I}\) ...

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

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

  9. 【网络流24题22】最长k可重线段集问题

    题面戳我 sol 千万!千万!不要理解错题意了!最长K可重,不是说线段最多K可重!你以为计算几何? 原文:使得在\(x\)轴上的任何一点\(p\),\(S\)中与直线\(x=p\)相交的开线段个数不超 ...

随机推荐

  1. 学习IIS & MVC的运行原理 (转)

    我一直疑惑于以下问题,从客户端发出一个请求,请求到达服务器端是怎样跟iis衔接起来的,而iis又是怎样读取我发布的代码的,并返回服务器上的文件.这其中是怎样的一个处理过程. 1:当你从浏览器中输入一个 ...

  2. MVC表单提交写法1

    初学MVC,感觉跟以前的aspx页面差别很大,我们就先来看看MVC的表单是怎么提交的吧. 现在我们用一个最简单的例子来看一看MVC是怎么提交表单的(这一个例子中,我们的关注点是如何提交表单,所以不涉及 ...

  3. 在制MO未取到FP

    原因:今天在制MO未取进去原因为业务人员维护验货客户尾缀时维护ZZ导致,需更新为C开头即可 SELECT * FROM IN_SFCHEADER WHERE MO_ID in('00110051832 ...

  4. BaseAnimation是基于开源的APP,致力于收集各种动画效果(最新版本1.3) (转)

    声明:部分动画来源于网络,本人只是想方便收集在一起,如果不妥请及时与我联系!谢谢 为了统一BaseAnimationApp签名,一定要方便以后大家自动更新...防止签名冲突,不能及时更新 1.3源码下 ...

  5. 使用IntelliJ IDEA,gradle开发Java web应用步骤

    最近 正在学习gradle构建工具的使用,看了一堆的文档,有点一知半解,索性动作实践一把,在以后的自己的项目中尝试使用看看.目前手头用的是IntelliJ IDEA 14,搭建了一天终于明白怎么集成g ...

  6. 在线编辑器CKeditor,CKfinder

    在线编辑器的分类: 常见的在线编辑器有很多,比较常用的有FCKeditor(在线编辑器——Ajax 浏览器 端服务器文件管理器),CKeditor(在线编辑器与服务器端文件管理器的分离,) 其中CKe ...

  7. 解析config文件 练手代码

    解析一个如下的CONFIG文件 #config.txt #SHTTPD Web 服务器配置文件示例 #侦听端口 ListenPort = 80 #最大并发访问客户端数目 MaxClient = 8 # ...

  8. linux / centos 安装SQL Server 2017 设置默认语言与排序规则Chinese_PRC_CI_AS

    安装 安装很简单参照官方教程 https://docs.microsoft.com/zh-cn/sql/linux/quickstart-install-connect-red-hat?view=sq ...

  9. Android内核的编译与测试

    1.下载Android内核 source.android.com/source->Downloading and Building Building Kernels 大概要花2个小时,其源码在培 ...

  10. 【译】微型ORM:PetaPoco【不完整的翻译】(转)

    出处:http://www.cnblogs.com/youring2/archive/2012/06/04/2532130.html PetaPoco是一款适用于.Net 和Mono的微小.快速.单文 ...