最长k可重线段集问题
Posted liguanlin1124
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了最长k可重线段集问题相关的知识,希望对你有一定的参考价值。
题解:
由于线段可以出现平行于$y$轴的情况,
我们要拆点。
然后分情况讨论。
具体方法不赘述。
代码:
#include<cmath> #include<queue> #include<cstdio> #include<vector> #include<cstring> #include<algorithm> using namespace std; #define N 2050 #define ll long long const int inf = 0x3f3f3f3f; const ll Inf = 0x3f3f3f3f3f3f3f3fll; inline int rd() { int f=1,c=0;char ch=getchar(); while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();} while(ch>=‘0‘&&ch<=‘9‘){c=10*c+ch-‘0‘;ch=getchar();} return f*c; } int n,m,hed[N],cnt=-1,S,T,tot=0; struct seg { int l,r; ll w; }s[N]; struct Pair { int x,id,k; Pair(){} Pair(int x,int i,int k):x(x),id(i),k(k){} }p[N]; bool cmp(Pair a,Pair b) { if(a.x!=b.x)return a.x<b.x; return a.k<b.k; } struct EG { int to,nxt; ll w,c; }e[N*N*4]; void ae(int f,int t,ll w,ll c) { e[++cnt].to = t; e[cnt].nxt = hed[f]; e[cnt].w = w; e[cnt].c = c; hed[f] = cnt; } void AE(int f,int t,ll w,ll c) { ae(f,t,w,c); ae(t,f,0,-c); } ll dep[N],fl[N]; int pre[N],fa[N]; bool vis[N]; queue<int>q; bool spfa() { memset(dep,0x3f,sizeof(dep)); dep[S] = 0,fl[S] = inf,vis[S] = 1; q.push(S); while(!q.empty()) { int u = q.front(); q.pop(); for(int j=hed[u];~j;j=e[j].nxt) { int to = e[j].to; if(e[j].w&&dep[to]>dep[u]+e[j].c) { dep[to] = dep[u]+e[j].c; fl[to] = min(fl[u],e[j].w); pre[to] = j,fa[to] = u; if(!vis[to]) { vis[to] = 1; q.push(to); } } } vis[u] = 0; } return dep[T]!=Inf; } ll mcmf() { ll ret = 0; while(spfa()) { ret+=fl[T]*dep[T]; int u = T; while(u!=S) { e[pre[u]].w-=fl[T]; e[pre[u]^1].w+=fl[T]; u = fa[u]; } } return ret; } vector<ll>ve[N]; int main() { n = rd(),m = rd(); S = 0,T = 1; memset(hed,-1,sizeof(hed)); int k = 0; for(int x,y,i=1;i<=n;i++) { s[i].l=rd(),x=rd(),s[i].r=rd(),y=rd(),s[i].w=(ll)sqrt(1ll*(s[i].r-s[i].l)*(s[i].r-s[i].l)+1ll*(x-y)*(x-y)); if(s[i].l>s[i].r) { swap(s[i].l,s[i].r); } p[++tot] = Pair(s[i].l,i,0); p[++tot] = Pair(s[i].r,i,1); } sort(p+1,p+1+tot,cmp); for(int las=-1,i=1;i<=tot;i++) { if(las!=p[i].x) { las = p[i].x; k++; } if(!p[i].k)s[p[i].id].l = k; else { if(s[p[i].id].l!=k)AE(s[p[i].id].l<<1|1,k<<1,1,-s[p[i].id].w); else AE(k<<1,k<<1|1,1,-s[p[i].id].w); } } AE(S,2,m,0);AE(k<<1|1,T,m,0); for(int i=1;i<k;i++) AE(i<<1|1,(i+1)<<1,m,0); for(int i=1;i<=k;i++) AE(i<<1,i<<1|1,m,0); printf("%lld ",-mcmf()); return 0; }
以上是关于最长k可重线段集问题的主要内容,如果未能解决你的问题,请参考以下文章