最长 \(k\) 可重线段集

题目大意

给定平面 \(x-O-y\) 上 \(n\) 个开线段组成的集合 \(I\) ,和一个正整数 \(k\) 。试设计一个算法,从开线段集合 \(I\) 中选取开线段集合 \(S \subseteq I\) ,使得在 \(x\) 轴上的任意一点 \(P\) , \(S\) 中与直线 \(x=p\) 相交的开线段个数不超过 \(k\) ,且 \(\sum_{z \in S}|z|\) 最大。这样的集合 \(S\) 称为开线段集合 \(I\) 的最长 \(k\) 可重线段集。 \(\sum_{z\in S}|z|\) 称为最长 \(k\) 可重线段集的长度。

对于任意开线段 \(z\) ,设其端点坐标为 \((x_0,y_0)\) 和 \((x_1,y_1)\) ,则开线段 \(z\) 的长度 \(|z|\) 定义为:

\[|z|=[\sqrt{(x_1-x_0)^2+(y_1-y_0)^2}]
\]

对于给定的开线段集合 \(I\) 和正整数 \(k\) ,计算开线段集合 \(I\) 的最长 \(k\) 可重线段集的长度。

分析

想要解决此题,可以先看一下与该题基本如出一辙的:最长 \(k\) 可重区间集[题解]

其实这道题和上述此题非常类似,只不过将水平的区间转化为了一些基本无规律处于二维平面内的线段。

那么我们还是可以把问题转化到 \(x\) 上,我们发现其实 \(y\) 坐标和题目的限制关系不大,我们只需要解决横坐标部分即可。

其实我们只需要把线段两个端点的 \(x\) 坐标转化为何上述题目一样的区间即可,就可以得到和上述题目一样的过程,具体分析可以点击上方链接,下面直接给出建图思路:

  • 将每个线段的左右端点的 \(x\) 坐标储存起来,并将线段 \(i\) 拆成 \(i\) 与 \(i'\) 分别表示点 \(i\) 的入点与出点,对于每对拆点,在他们中间连接一条流量为 \(1\) ,费用为线段长度的边。

  • 建立一个超级源点超级汇点,超级源点向真正的源点连接一条流量为 \(k\) ,费用为 \(0\) 的边,并再将源点向每条线段的入点连接一条流量为 \(1\) ,费用为 \(0\) 的边,每条线段的出点向超级汇点连接一条流量为 \(1\) ,费用为 \(0\) 的边。

  • 对于左右端点形成的区间互不相交的线段,在他们之间建立一条流量为 \(+\infty\) ,费用为 \(0\) 的边。

这样就可以直接跑最大费用了。

需要注意两个地方:

  • 本文一开始的链接中详细论述了线段连接有序性的必要,所以我们必须要排序或是要保证线段连接的有序。

  • 对于两条线段,如果他们完全相同的话,我们仍然需要将其计算在限制内,所以需要进行特殊判断,不能进行连边。

最后代码如下:

CODE

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=5e2+10,INF=0x7fffffff;
int n,k,s,t,_s,ans;
struct node{ int l,r,len; }sec[N];
inline int read()
{
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
return s*w;
}
inline bool cmp(node x,node y) { return x.l<y.l; }
int tot=-1,v[2*N*N],w[2*N*N],pay[2*N*N],nex[2*N*N],first[2*N];
inline void Add(int x,int y,int z,int c)
{
nex[++tot]=first[x];
first[x]=tot;
v[tot]=y,w[tot]=z,pay[tot]=c;
}
bool vis[2*N];
int pre[2*N],dis[2*N],Min[2*N];
inline bool SPFA()
{
for(register int i=s;i<=t;i++) dis[i]=-INF;
for(register int i=s;i<=t;i++) vis[i]=false;
queue<int> q;
q.push(s);
vis[s]=true,dis[s]=0,Min[s]=INF;
while(!q.empty()){
int now=q.front(); q.pop();
vis[now]=false;
for(register int i=first[now];i!=-1;i=nex[i]){
int to=v[i];
if(!w[i]) continue;
if(dis[to]<dis[now]+pay[i]){
dis[to]=dis[now]+pay[i];
Min[to]=min(Min[now],w[i]);
pre[to]=i;
if(!vis[to]) q.push(to),vis[to]=true;
}
}
}
return dis[t]!=-INF;
}
inline void EK()
{
while(SPFA()){
ans+=Min[t]*dis[t];
int temp=t,i;
while(temp!=s){
i=pre[temp];
w[i]-=Min[t];
w[i^1]+=Min[t];
temp=v[i^1];
}
}
}
signed main()
{
memset(first,-1,sizeof(first));
n=read(),k=read();
for(register int i=1;i<=n;i++){
int _x1=read(),_y1=read(),_x2=read(),_y2=read();
sec[i].l=min(_x1,_x2),sec[i].r=max(_x1,_x2);
sec[i].len=(int)sqrt((_x1-_x2)*(_x1-_x2)+(_y1-_y2)*(_y1-_y2));
}
s=0,_s=2*n+1,t=2*n+2;
sort(sec+1,sec+n+1,cmp);
Add(s,_s,k,0),Add(_s,s,0,0);
for(register int i=1;i<=n;i++){
Add(_s,i,1,0),Add(i,_s,0,0);
Add(i,i+n,1,sec[i].len),Add(i+n,i,0,-sec[i].len);
Add(i+n,t,1,0),Add(t,i+n,0,0);
}
for(register int i=1;i<=n;i++){
for(register int j=i+1;j<=n;j++){
if(sec[i].l==sec[i].r&&sec[j].l==sec[j].r&&sec[i].l==sec[j].l) continue;
if(sec[j].l>=sec[i].r||sec[i].l>=sec[j].r) Add(i+n,j,INF,0),Add(j,i+n,0,0);
}
}
EK();
printf("%lld\n",ans);
return 0;
}

[网络流24题]最长k可重线段集[题解]的更多相关文章

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

随机推荐

  1. 【Azure 应用服务】由 Azure Functions runtime is unreachable 的错误消息推导出 ASYNC(异步)和 SYNC(同步)混用而引起ThreadPool耗尽问题

    问题描述 在Azure Function Portal上显示: Azure Functions runtime is unreachable,引起的结果是Function App目前不工作,但是此前一 ...

  2. DM8_Linux详细安装步骤

    (从虚拟机配置讲起,有基础的可以直接看二,谢谢) 一.虚拟机的安装和配置 软件:virtualbox 系统:centos7 工具:Xshell 官网下载centos7,使用virtualbox安装ce ...

  3. 使用ONNX将模型转移至Caffe2和移动端

    使用ONNX将模型转移至Caffe2和移动端 本文介绍如何使用 ONNX 将 PyTorch 中定义的模型转换为 ONNX 格式,然后将其加载到 Caffe2 中.一旦进入 Caffe2, 就可以运行 ...

  4. pytorch生成对抗示例

    pytorch生成对抗示例 本文对ML(机器学习)模型的安全漏洞的认识,并将深入了解对抗性机器学习的热门话题.图像添加难以察觉的扰动会导致模型性能大不相同.通过图像分类器上的示例探讨该主题.使用第一种 ...

  5. CodeGen用户定义的扩展令牌

    CodeGen用户定义的扩展令牌 用户定义的扩展令牌是一种特殊的令牌,开发人员可以确定令牌的名称以及在代码生成过程中遇到令牌时要插入的值. CodeGen支持多种机制,允许通过以下方式实现用户定义的令 ...

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

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

  7. 面试官:给我讲讲SpringBoot的依赖管理和自动配置?

    1.前言 从Spring转到SpringBoot的xdm应该都有这个感受,以前整合Spring + MyBatis + SpringMVC我们需要写一大堆的配置文件,堪称配置文件地狱,我们还要在pom ...

  8. 基于TensorFlow的服装分类

    1.导包 #导入TensorFlow和tf.keras import tensorflow as tf from tensorflow import keras # Helper libraries ...

  9. spring boot 并发请求,其他系统接口,丢失request的header信息【多线程、线程池、@Async 】

    场景:一次迭代在灰度环境发版时,测试反馈说我开发的那个功能,查询接口有部分字段数据是空的,后续排查日志,发现日志如下: feign.RetryableException: cannot retry d ...

  10. sql优化问题

    一.分析阶段 一 般来说,在系统分析阶段往往有太多需要关注的地方,系统各种功能性.可用性.可靠性.安全性需求往往吸引了我们大部分的注意力,但是,我们必须注意,性能 是很重要的非功能性需求,必须根据系统 ...