正题
题目链接:https://jzoj.net/senior/#main/show/1405
题目大意
两个平行于xxx轴的线上有若干个点,求连接所有点需要多少距离的线。
解题思路
在同一平行线上的相邻的连边,然后在不同的上面的话就离最近的两个,跑最小生成树即可。
codecodecode
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cctype>
#include<cmath>
#define sqr(x) (1ll*(x)*(x))
using namespace std;
const int N=601000*2;
struct node{int x,y;long long w;
}a[N*2];
int n,m,x1,x2,fa[N],y[N],tot;
double ans;
int read() {int x=0,f=1; char c=getchar();while(!isdigit(c)) {if(c=='-')f=-f;c=getchar();}while(isdigit(c)) x=(x<<1)+(x<<3)+c-48,c=getchar();return x*f;
}
bool cmp(node x,node y)
{return x.w<y.w;}
int find(int x)
{return (fa[x]==x)?x:(fa[x]=find(fa[x]));}
int main()
{n=read();m=read();x1=read();x2=read();for(int i=1;i<=n;i++)fa[i]=i,y[i]=y[i-1]+read();for(int i=n+1;i<=n+m;i++)fa[i]=i,y[i]=y[i-1]*(i!=n+1)+read();for(int i=1;i<n;i++)a[++tot]=(node){i,i+1,sqr(y[i+1]-y[i])};for(int i=n+1;i<n+m;i++)a[++tot]=(node){i,i+1,sqr(y[i+1]-y[i])};int l=n+1;for(int i=1;i<=n;i++){while(l<n+m&&y[l]<y[i]) l++;a[++tot]=(node){i,l,1ll*sqr(y[i]-y[l])+1ll*sqr(x1-x2)};if(l>n+1) a[++tot]=(node){i,l-1,1ll*sqr(y[i]-y[l-1])+1ll*sqr(x1-x2)}; }sort(a+1,a+1+tot,cmp);int z=n+m-1;for(int i=1;i<=tot;i++){int Fa=find(a[i].x),Fb=find(a[i].y);if(Fa==Fb) continue;ans+=sqrt(1.0*a[i].w);z--;fa[Fa]=Fb;if(!z) break;}printf("%.2lf",ans);
}