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

传送门

其实和最长k可重区间集问题差不多诶……

把这条开线段给压成x轴上的一条线段,然后按上面说的那种方法做即可

然而有一个坑点是线段可以垂直于x轴,然后一压变成一个点,连上正权环,求最长路……然后spfa他就死了……

怎么解决呢……把每一个区间的左右端点坐标扩大两倍,如果相等就$--l[i]$,否则$++l[i]$,这样的话能保证本来不能覆盖的点仍不能覆盖,本来可以覆盖的点仍可以覆盖

似乎讲不清楚……感性理解一下好了……

 1 //minamoto
 2 #include<iostream>
 3 #include<cstdio>
 4 #include<queue>
 5 #include<cstring>
 6 #include<cmath>
 7 #include<algorithm>
 8 #define inf 0x3f3f3f3f
 9 #define ll long long
10 using namespace std;
11 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
12 char buf[1<<21],*p1=buf,*p2=buf;
13 inline int read(){
14     #define num ch-'0'
15     char ch;bool flag=0;int res;
16     while(!isdigit(ch=getc()))
17     (ch=='-')&&(flag=true);
18     for(res=num;isdigit(ch=getc());res=res*10+num);
19     (flag)&&(res=-res);
20     #undef num
21     return res;
22 }
23 const int N=1005,M=4005;
24 int ver[M],Next[M],head[N],edge[M],flow[M],tot=1;
25 int dis[N],disf[N],vis[N],Pre[N],last[N],n,s,t,k;
26 inline ll sqr(int x){return 1ll*x*x;}
27 inline void add(int u,int v,int f,int e){
28     ver[++tot]=v,Next[tot]=head[u],head[u]=tot,flow[tot]=f,edge[tot]=e;
29     ver[++tot]=u,Next[tot]=head[v],head[v]=tot,flow[tot]=0,edge[tot]=-e;
30 }
31 queue<int> q;
32 bool spfa(){
33     memset(dis,0xef,sizeof(dis));
34     q.push(s),dis[s]=0,disf[s]=inf,Pre[t]=-1;
35     while(!q.empty()){
36         int u=q.front();q.pop();vis[u]=0;
37         for(int i=head[u];i;i=Next[i]){
38             int v=ver[i];
39             if(flow[i]&&dis[v]<dis[u]+edge[i]){
40                 dis[v]=dis[u]+edge[i],Pre[v]=u,last[v]=i;
41                 disf[v]=min(disf[u],flow[i]);
42                 if(!vis[v]) vis[v]=1,q.push(v);
43             }
44         }
45     }
46     return ~Pre[t];
47 }
48 ll dinic(){
49     int maxflow=0;ll maxcost=0;
50     while(spfa()){
51         int u=t;
52         maxflow+=disf[t],maxcost+=1ll*disf[t]*dis[t];
53         while(u!=s){
54             flow[last[u]]-=disf[t];
55             flow[last[u]^1]+=disf[t];
56             u=Pre[u];
57         }
58     }
59     return maxcost;
60 }
61 int l[N],r[N],x[N],y[N],st[N],val[N],m=0;
62 int main(){
63     n=read(),k=read();
64     for(int i=1;i<=n;++i){
65         l[i]=read(),x[i]=read(),r[i]=read(),y[i]=read();
66         val[i]=sqrt(sqr(y[i]-x[i])+sqr(r[i]-l[i]));
67         l[i]*=2,r[i]*=2;
68         l[i]==r[i]?(--l[i]):(++l[i]);
69         st[++m]=l[i],st[++m]=r[i];
70     }
71     sort(st+1,st+1+m);
72     m=unique(st+1,st+1+m)-st-1;
73     s=0,t=m+1;
74     for(int i=s;i<t;++i) add(i,i+1,k,0);
75     for(int i=1;i<=n;++i){
76         l[i]=lower_bound(st+1,st+1+m,l[i])-st;
77         r[i]=lower_bound(st+1,st+1+m,r[i])-st;
78         add(l[i],r[i],1,val[i]);
79     }
80     printf("%lld\n",dinic());
81     return 0;
82 }

猜你喜欢

转载自www.cnblogs.com/bztMinamoto/p/9504034.html