[网络流24题]最长k可重线段集[题解]
最长 \(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|\) 定义为:
\]
对于给定的开线段集合 \(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可重线段集[题解]的更多相关文章
- 网络流24题-最长k可重线段集问题
最长k可重线段集问题 时空限制1000ms / 128MB 题目描述 给定平面 x−O−y 上 n 个开线段组成的集合 I,和一个正整数 k .试设计一个算法,从开线段集合 I 中选取出开线段集合 S ...
- [网络流24题]最长k可重区间集[题解]
最长 \(k\) 可重区间集 题目大意 给定实心直线 \(L\) 上 \(n\) 个开区间组成的集合 \(I\) ,和一个正整数 \(k\) ,试设计一个算法,从开区间集合 \(I\) 中选取开区间集 ...
- [网络流24题] 最长k可重线段集问题 (费用流)
洛谷传送门 LOJ传送门 最长k可重区间集问题的加强版 大体思路都一样的,不再赘述,但有一些细节需要注意 首先,坐标有负数,而且需要开$longlong$算距离 但下面才是重点: 我们把问题放到了二维 ...
- COGS743. [网络流24题] 最长k可重区间集
743. [网络流24题] 最长k可重区间集 ★★★ 输入文件:interv.in 输出文件:interv.out 简单对比时间限制:1 s 内存限制:128 MB «问题描述: «编 ...
- [网络流24题] 最长k可重区间集
https://www.luogu.org/problemnew/show/3358 以区间(1,5),(2,6),(7,8)为例 建模方法一: 建模方法二: 离散化区间端点 相当于找k条费用最大的不 ...
- [网络流24题] 最长K可重区间集问题
题目链接:戳我 当时刷24题的时候偷了懒,没有写完,结果落下这道题没有写qwq结果今天考试T3中就有一部分要用到这个思想,蒟蒻我硬是没有想到网络流呜呜呜 最大费用流. 就是我们考虑将问题转化一下,转化 ...
- [网络流24题] 最长k可重区间集问题 (费用流)
洛谷传送门 LOJ传送门 很巧妙的建图啊...刚了$1h$也没想出来,最后看的题解 发现这道题并不类似于我们平时做的网络流题,它是在序列上的,且很难建出来二分图的形. 那就让它在序列上待着吧= = 对 ...
- 【网络流24题】最长k可重线段集(费用流)
[网络流24题]最长k可重线段集(费用流) 题面 Cogs的数据有问题 Loj 洛谷 题解 这道题和最长k可重区间集没有区别 只不过费用额外计算一下 但是,还是有一点要注意的地方 这里可以是一条垂直的 ...
- 【刷题】LOJ 6227 「网络流 24 题」最长k可重线段集问题
题目描述 给定平面 \(\text{xoy}\) 上 \(n\) 个开线段组成的集合 \(\text{I}\) ,和一个正整数 \(k\) ,试设计一个算法. 从开线段集合 \(\text{I}\) ...
随机推荐
- newbee-mall开源项目被慕课网拿去做课程,然后我毫不知情,这又是什么骚操作?
万万没想到,这种事情会发生在我身上. 之前写过<开源囧事>系列而且已经写了四篇,四次开源囧事如下: <开源囧事(一)捅娄子了,写个bug被国家信息安全漏洞共享平台抓到了?> & ...
- double类型数据有的时候null的判断
double不是Double,无法通过 == null来判断 如何进行double的null判断呢 double avg = avg.getValue() // 此时不会报错 // 通过如下进行判断 ...
- Halide应用开发
Halide应用开发 1. 基本原理 1.1.介绍 随着人工智能的普及,深度学习网络的不断涌现,为了让各硬件(CPU, GPU, NPU,...)能够支持深度学习应用,各硬件芯片需要软件库去支持高性能 ...
- Consistent 与 Mirrored 视角
Consistent 与 Mirrored 视角 在进行分布式训练时,OneFlow 框架提供了两种角度看待数据与模型的关系,被称作 consistent 视角与 mirrored 视角. 本文将介绍 ...
- FFmpeg扩展开发
FFmpeg扩展开发 对FFmpeg RTMP/FLV部分做了扩展,用于支持H.265. 针对<video_file_format_spec_v10_1> VIDEODATA部分扩展如下: ...
- Java设计模式(3:接口隔离原则和迪米特法则详解)
一.接口隔离原则 使用多个接口,而不使用单一的接口,客户端不应该依赖它不需要的接口.尽量的细化接口的职责,降低类的耦合度. 我们先来看一个例子: 小明家附近新开了一家动物园,里面有老虎.鸟儿.长颈鹿. ...
- Ubuntu18.04的下载与安装(全过程纪录)
unbuntu18.04的下载与安装 注:由于大部分过程是以图片形式说明,所以可能会导致网页浏览不流畅 前言 有时候由于个人计算机中文件的频繁移动,导致虚拟机的镜像文件有时候莫名删除了或者不见了(说到 ...
- mysqldump 使用规范
数据库很重要,没有备份,数据丢失只能跑路.所以还是做好备份吧! 目录 一.工具介绍 二.工具特点 三.备份权限 四.工具使用限制 五.已知BUG 六.备份前注意事项 6.1 需要长时间备份或导入时,请 ...
- Java知识复习(三)
Set里的元素是不能重复的,那么用什么方法来区分重复与否呢? 是用==还是equals()? 它们有何区别?用contains来区分是否有重复的对象.还是都不用. 在比较时先调用hashCode方法, ...
- 透彻详解(3)旁路电容100nF_0.1uF的由来计算
原文地址点击这里: 前一节我们已经详细解释了旁路电容在数字电路系统中所起的基本且重要作用,即储能与为高频噪声电流提供低阻抗路径,尽管还并未给旁路电容的这些功能概括一个"高大上"的名 ...