最长 \(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. Camera噪声问题

    Camera噪声问题 Camera RGB 域的噪声 以上部分属于sensor processing,接下来的部分属于color.luminance processing. gamma gamma是在 ...

  2. CVPR2018论文看点:基于度量学习分类与少镜头目标检测

    CVPR2018论文看点:基于度量学习分类与少镜头目标检测 简介 本文链接地址:https://arxiv.org/pdf/1806.04728.pdf 距离度量学习(DML)已成功地应用于目标分类, ...

  3. 利用NVIDIA-NGC中的MATLAB容器加速语义分割

    利用NVIDIA-NGC中的MATLAB容器加速语义分割 Speeding Up Semantic Segmentation Using MATLAB Container from NVIDIA NG ...

  4. Django OperationalError错误解决

    Django项目实践中通过页面http://127.0.0.1:8000/admin/添加数据时报错,见下图 解决方法: 参考链接: https://stackoverflow.com/questio ...

  5. Redis 入门权威指北

    前言 看看业务遇到了什么问题? 我们要从互联网架构的演变之路开始说起Redis的前世今生. 在我们小的时候,网络世界好像就是只有通过大屁股台式机才能进入一样,彼时的手机只是用来打打电话,发发短信,网上 ...

  6. 【NX二次开发】Block UI 线条颜色/线型/宽度

    属性说明 常规         类型 描述     BlockID     String 控件ID     Enable     Logical 是否可操作     Group     Logical ...

  7. 【NX二次开发】Block UI 通过浏览选择文件

    属性说明 属性   类型   描述   常规           BlockID    String    控件ID    Enable    Logical    是否可操作    Group    ...

  8. 『言善信』Fiddler工具 — 16、使用Fiddler抓取移动端App请求

    目录 1.抓取Android移动端App请求 2.抓取IOS移动端App请求 3.总结: 1.抓取Android移动端App请求 前提: 因为Fiddler抓包的原理就是通过代理,所以确保被测终端要和 ...

  9. DB2 SQL0805N解决和思考

    一.报错现象 这是一个在使用 DB2数据库过程中比较常见的错误, 报错信息如下 Exception stack trace: com.ibm.db2.jcc.am.SqlException: DB2 ...

  10. git stash回退

    目录 1.起因 2. 问题出现 3.修复 4. 注意 1.起因 这个问题要从今天刚遇到的事儿说起,昨晚代码出了个乌龙事件,本来正在dev分支进行新功能的开发,但是测试出现的问题是在release 分支 ...