题目描述

给定平面 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: 复制

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

17

说明

1\leq n\leq5001≤n≤500

1 \leq k \leq 131≤k≤13

这题与最长k可重区间集问题本质上是一样的,

但是有一种特殊情况,当这条直线垂直于$y$轴时,我们在连边的过程中会产生负环

怎么办呢?

这里有一个神仙操作

把两个点的$x$值全部*2,若相同,则较小的-1,否则较小的+1

#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
#include<vector>
#include<cmath>
#define int long long
#define AddEdge(x,y,z,f) add_edge(x,y,z,f),add_edge(y,x,-z,0)
using namespace std;
const int MAXN=1e5+;
const int INF=1e8+;
inline int read()
{
char c=getchar();int x=,f=;
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){x=x*+c-'';c=getchar();}
return x*f;
}
int N,K,S,T;
int anscost=;
struct node
{
int u,v,w,f,nxt;
}edge[MAXN];
int head[MAXN],num=;
inline void add_edge(int x,int y,int z,int f)
{
edge[num].u=x;
edge[num].v=y;
edge[num].w=z;
edge[num].f=f;
edge[num].nxt=head[x];
head[x]=num++;
}
int Pre[MAXN],vis[MAXN],dis[MAXN];
bool SPFA()
{
queue<int>q;
memset(dis,0x3f,sizeof(dis));
memset(vis,,sizeof(vis));
dis[S]=;
q.push(S);
while(q.size()!=)
{
int p=q.front();q.pop();
vis[p]=;
for(int i=head[p];i!=-;i=edge[i].nxt)
{
if(dis[edge[i].v]>dis[p]+edge[i].w&&edge[i].f)
{
dis[edge[i].v]=dis[p]+edge[i].w;
Pre[edge[i].v]=i;
if(!vis[edge[i].v])
vis[edge[i].v]=,q.push(edge[i].v);
}
}
}
return dis[T]<=INF;
}
void f()
{
int nowflow=INF;
for(int now=T;now!=S;now=edge[Pre[now]].u)
nowflow=min(nowflow,edge[Pre[now]].f);
for(int now=T;now!=S;now=edge[Pre[now]].u)
edge[Pre[now]].f-=nowflow,
edge[Pre[now]^].f+=nowflow;
anscost+=nowflow*dis[T];
}
void MCMF()
{
int ans=;
while(SPFA())
f();
printf("%lld\n",-anscost);
}
int L[MAXN],R[MAXN],date[MAXN],tot=;
struct Point
{
int xx1,yy1,xx2,yy2,L;
}P[MAXN];
double GetL(int n)
{
return floor((double)sqrt((P[n].xx1-P[n].xx2)*(P[n].xx1-P[n].xx2) + (P[n].yy1-P[n].yy2)*(P[n].yy1-P[n].yy2)));
}
main()
{
#ifdef WIN32
freopen("a.in","r",stdin);
#else
#endif
memset(head,-,sizeof(head));
N=read();K=read();
for(int i=;i<=N;i++)
{
P[i].xx1=read(),P[i].yy1=read(),P[i].xx2=read(),P[i].yy2=read();
if(P[i].xx1>P[i].xx2)
swap(P[i].xx1,P[i].xx2),
swap(P[i].yy1,P[i].yy2);
P[i].L=GetL(i);
P[i].xx1*=;
P[i].xx2*=;
if(P[i].xx1==P[i].xx2) P[i].xx1--;
else P[i].xx1++;
date[++tot]=P[i].xx1,date[++tot]=P[i].xx2;
} sort(date+,date+tot+);
int num=unique(date+,date+tot+)-date-;
for(int i=;i<=num-;i++)
AddEdge(i,i+,,INF);
for(int i=;i<=N;i++)
{
P[i].xx1=lower_bound(date+,date+num+,P[i].xx1)-date; P[i].xx2=lower_bound(date+,date+num+,P[i].xx2)-date; AddEdge(P[i].xx1,P[i].xx2,-P[i].L,);
}
S=,T=num*;
AddEdge(S,,,K);
AddEdge(num,T,,K);
MCMF();
return ;
}

洛谷P3357 最长k可重线段集问题(费用流)的更多相关文章

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

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

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

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

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

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

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

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

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

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

  6. P3357 最长k可重线段集问题 网络流

    P3357 最长k可重线段集问题 题目描述 给定平面 x-O-yx−O−y 上 nn 个开线段组成的集合 II,和一个正整数 kk .试设计一个算法,从开线段集合 II 中选取出开线段集合 S\sub ...

  7. 【网络流24题】最长k可重区间集(费用流)

    [网络流24题]最长k可重区间集(费用流) 题面 Cogs Loj 洛谷 题解 首先注意一下 这道题目里面 在Cogs上直接做就行了 洛谷和Loj上需要判断数据合法,如果\(l>r\)就要交换\ ...

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

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

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

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

随机推荐

  1. 项目随笔@Service("testService")-------第二篇

    在springmvc中使用注解已经司空见惯了,今天见到了@Service("xxx")这种形式,让我大吃一惊.原来在service后面可以加参数,作为该service的名字,在sp ...

  2. Java之关于面向对象

    面向对象,呃,别给我说程序员找不到对象,那是windows才会出现的情况~~~ 就简单记下笔记什么的吧. 1.关于定义和赋值 之前总是搞混淆,说到底是没有搞清楚. shit bigOne=new sh ...

  3. WEBGL学习【七】画布绘图

    主要是对WEBGL的绘图部分进行了进一步加强的认识和理解 <!DOCTYPE HTML> <html lang="en"> <head> < ...

  4. 2019-04-03 SQL Group By某列,预先对该列进行一个预处理,提炼出共有的信息,即关键字case when 列名什么条件 then 赋值 else 赋值 end as 新列名

    select sum(发行金额) from( select PoolNameFormat,count(cast(ItemValue as decimal(19,4))) as 发行笔数,sum(cas ...

  5. 启动 Appium 自带模拟器

    1.先在sclipse中新建并打开一个设备 2.启动appium 3.安装apk 打开cmd  并在sdk安装目录的tools文件夹下输入安装命令adb install xxx.apk(在这之前需要把 ...

  6. 如何计算合适的InnoDB log file size

    原文链接:http://www.mysqlperformanceblog.com/2008/11/21/how-to-calculate-a-good-innodb-log-file-size/ Pe ...

  7. nyoj 20水

    #include<stdio.h> #include<string.h> #define N 110000 struct node { int u,v,next; }bian[ ...

  8. OGG For Bigdata To Kafka同步问题处理

    一.问题报错 -- :: ERROR OGG- Java or JNI exception: oracle.goldengate.util.GGException: Error detected ha ...

  9. 0111MySQL优化的奇技淫巧之STRAIGHT_JOIN

    转自博客http://huoding.com/2013/06/04/261 问题 通过「SHOW FULL PROCESSLIST」语句很容易就能查到问题SQL,如下: SELECT post.* F ...

  10. HBase读取代码

    HBase读取代码 需要的jar包: activation-1.1.jar aopalliance-1.0.jar apacheds-i18n-2.0.0-M15.jar apacheds-kerbe ...