洛谷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\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可重线段集问题(费用流)的更多相关文章
- 洛谷P3357 最长k可重线段集问题(费用流)
传送门 其实和最长k可重区间集问题差不多诶…… 把这条开线段给压成x轴上的一条线段,然后按上面说的那种方法做即可 然而有一个坑点是线段可以垂直于x轴,然后一压变成一个点,连上正权环,求最长路……然后s ...
- 洛谷 P3357 最长k可重线段集问题【最大流】
pre:http://www.cnblogs.com/lokiii/p/8435499.html 和最长k可重区间集问题差不多,也就是价值的计算方法不一样,但是注意这里可能会有x0==x1的情况也就是 ...
- 洛谷P3358 最长k可重区间集问题(费用流)
题目描述 对于给定的开区间集合 I 和正整数 k,计算开区间集合 I 的最长 k可重区间集的长度. 输入输出格式 输入格式: 的第 1 行有 2 个正整数 n和 k,分别表示开区间的个数和开区间的可重 ...
- 【网络流24题】最长k可重线段集(费用流)
[网络流24题]最长k可重线段集(费用流) 题面 Cogs的数据有问题 Loj 洛谷 题解 这道题和最长k可重区间集没有区别 只不过费用额外计算一下 但是,还是有一点要注意的地方 这里可以是一条垂直的 ...
- [网络流24题] 最长k可重线段集问题 (费用流)
洛谷传送门 LOJ传送门 最长k可重区间集问题的加强版 大体思路都一样的,不再赘述,但有一些细节需要注意 首先,坐标有负数,而且需要开$longlong$算距离 但下面才是重点: 我们把问题放到了二维 ...
- P3357 最长k可重线段集问题 网络流
P3357 最长k可重线段集问题 题目描述 给定平面 x-O-yx−O−y 上 nn 个开线段组成的集合 II,和一个正整数 kk .试设计一个算法,从开线段集合 II 中选取出开线段集合 S\sub ...
- 【网络流24题】最长k可重区间集(费用流)
[网络流24题]最长k可重区间集(费用流) 题面 Cogs Loj 洛谷 题解 首先注意一下 这道题目里面 在Cogs上直接做就行了 洛谷和Loj上需要判断数据合法,如果\(l>r\)就要交换\ ...
- 洛谷P3358 最长k可重区间集问题(费用流)
传送门 因为一个zz错误调了一个早上……汇点写错了……spfa也写错了……好吧好像是两个…… 把数轴上的每一个点向它右边的点连一条边,容量为$k$,费用为$0$,然后把每一个区间的左端点向右端点连边, ...
- [网络流24题] 最长k可重区间集问题 (费用流)
洛谷传送门 LOJ传送门 很巧妙的建图啊...刚了$1h$也没想出来,最后看的题解 发现这道题并不类似于我们平时做的网络流题,它是在序列上的,且很难建出来二分图的形. 那就让它在序列上待着吧= = 对 ...
随机推荐
- vue 子组件向父组件传值通信
父组件 子组件 子组件用this.$emit
- es6学习 http://es6.ruanyifeng.com/
基础学习 http://es6.ruanyifeng.com/ 够了 1字符串 字符串的遍历器接口 for (let codePoint of 'foo') { console.log(code ...
- Eigen库对齐问题:declspec(align('16')) 的形参将不被对齐
一:错误提示:error C2719: '_Val': formal parameter with __declspec(align('16')) won't be aligned 英文提示:erro ...
- 【转】DBSCAN密度聚类算法
DBSCAN(Density-Based Spatial Clustering of Applications with Noise,具有噪声的基于密度的聚类方法)是一种很典型的密度聚类算法,和K-M ...
- POJ 1811 Prime Test( Pollard-rho整数分解经典题 )
链接:传送门 题意:输入 n ,判断 n 是否为素数,如果是合数输出 n 的最素因子 思路:Pollard-rho经典题 /************************************** ...
- MYSQL: sql中某一个字段内容为用逗号分割的字符串转换成多条数据
场景: 表名:testsuer id name 1 小红,小李,李红,小法 要结果值为: 1 小红 1 小李 1 李红 1 小法 MYSQL函数解释 ...
- js生产随机数
var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz"; var string_le ...
- 执行目标文件引发的问题:syntax error: word unexpected (expe...
今天不小心把一个目标文件当成了可执行文件放到开发板上进行执行,结果出现了这样一个问题:./hello_qt: line 1: syntax error: word unexpected (expect ...
- 机房工程-在线式、后备式UPS选择(转载)
原文网址:http://oa.yesky.com/10/31061510all.shtml#p31061510 1后备式UPS还是在线式UPS? 作为机房设备的一项重要保护措施,UPS起着无可替代的作 ...
- 洛谷——P1030 求先序排列
https://www.luogu.org/problem/show?pid=1030#sub 题目描述 给出一棵二叉树的中序与后序排列.求出它的先序排列.(约定树结点用不同的大写字母表示,长度< ...