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

时间:2023-12-21 16:46:44

洛谷传送门 LOJ传送门

最长k可重区间集问题的加强版

大体思路都一样的,不再赘述,但有一些细节需要注意

首先,坐标有负数,而且需要开$longlong$算距离

但下面才是重点:

我们把问题放到了二维平面内,如果出现了垂直于$x$轴的线段,该如何处理呢?直接当成线段处理显然不可取

假设这条线段的横坐标是$x$

1.它不会对从$x$开始的倾斜线段产生任何影响,但会和穿过$x$的倾斜直线抢位置

2.它会和同样在$x$垂直的线段抢位置

我用了一个比较笨的做法,先把横坐标离散,再把离散后的横坐标抻成原来的$2$倍,垂直线段横坐标为$2x-1$,倾斜线段横坐标是$2x$,问题就被解决了

 #include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N1 2005
#define M1 200010
#define ll long long
#define dd double
#define inf 0x3f3f3f3f
#define maxn 100000
using namespace std; int gint()
{
int ret=,fh=;char c=getchar();
while(c<''||c>''){if(c=='-')fh=-;c=getchar();}
while(c>=''&&c<=''){ret=ret*+c-'';c=getchar();}
return ret*fh;
}
int n,K,S,T;
struct Edge{
int head[N1],to[M1<<],nxt[M1<<],flow[M1<<],dis[M1<<],cte;
void ae(int u,int v,int F,int D)
{
cte++; to[cte]=v; flow[cte]=F; dis[cte]=D;
nxt[cte]=head[u]; head[u]=cte;
}
}e; int que[M1<<],hd,tl,dis[N1],id[N1],flow[N1],use[N1];
int spfa()
{
int x,j,v;
memset(dis,-,sizeof(dis)); memset(flow,,sizeof(flow)); memset(use,,sizeof(use));
hd=,tl=; que[++tl]=S; dis[S]=; use[S]=; flow[S]=inf;
while(hd<=tl)
{
x=que[hd++];
for(j=e.head[x];j;j=e.nxt[j])
{
v=e.to[j];
if( e.flow[j]> && dis[v]<dis[x]+e.dis[j] )
{
dis[v]=dis[x]+e.dis[j]; id[v]=j;
flow[v]=min(flow[x],e.flow[j]);
if(!use[v]) que[++tl]=v, use[v]=;
}
}
use[x]=;
}
return dis[T]!=-;
}
int EK()
{
int tcost=,mxflow=,x;
while(spfa())
{
mxflow+=flow[T]; tcost+=flow[T]*dis[T];
for(x=T;x!=S;x=e.to[id[x]^])
{
e.flow[id[x]]-=flow[T];
e.flow[id[x]^]+=flow[T];
}
}
return tcost;
} int l[N1],r[N1],p[N1],len[N1],t[N1<<],cnt;
int main()
{
scanf("%d%d",&n,&K);
int i,j,x,y,ma; e.cte=;
for(i=;i<=n;i++)
{
l[i]=gint(), x=gint(), r[i]=gint(), y=gint();
if(l[i]>r[i]) swap(l[i],r[i]), swap(x,y);
len[i]=sqrt( 1ll*(r[i]-l[i])*(r[i]-l[i])+1ll*(y-x)*(y-x) );
if(l[i]!=r[i]) r[i]--; else p[i]=;
t[++cnt]=l[i], t[++cnt]=r[i];
}
sort(t+,t+cnt+); cnt=unique(t+,t+cnt+)-(t+);
for(i=;i<=n;i++)
{
x=lower_bound(t+,t+cnt+,l[i])-t;
y=lower_bound(t+,t+cnt+,r[i])-t;
if(p[i]){ l[i]=x*-, r[i]=y*-; }
else{ l[i]=x*; r[i]=y*; }
}
S=; T=cnt*+;
for(i=;i<=n;i++) e.ae(l[i],r[i]+,,len[i]), e.ae(r[i]+,l[i],,-len[i]);
for(i=;i<=cnt*;i++) e.ae(i,i+,K,), e.ae(i+,i,,); e.ae(S,,K,); e.ae(,S,,);
printf("%d\n",EK());
return ;
}