https://www.luogu.org/problem/show?pid=2212
很神奇啊
一共2000個點,那麼最多有4e6條邊;
如果通prim取最小生成樹的話就是吻過的;
然後我又試了一下kruskal的算法
結果炸了;
必須要安按秩合併,光路徑壓縮是不行的;
假如有一個數據,不斷在合併的時候合併一個樹的根節點,那麼路徑壓縮有沒有用;
最後一下子路徑壓縮,就可以卡到O(n)
加上遞歸和一個if,還有一開始排序的時間,就直接炸掉了;
#include<bits/stdc++.h>
#define Ll long long
using namespace std;
const Ll N=2e3+5;
struct cs{int x,y,v;}a[N*N];
int x[N],y[N],ll,f[N],siz[N];
int n,m,ans,sum;
bool cmp(cs x,cs y){return x.v<y.v;}
int get(int x){if(f[x]==0)return x;return f[x]=get(f[x]);}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)scanf("%d%d",&x[i],&y[i]);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++){
int v=(x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]);
if(v>=m)a[++ll].x=i,a[ll].y=j,a[ll].v=v;
}
sort(a+1,a+ll+1,cmp);
for(int i=1;i<=n;i++) siz[i]=1;
for(int i=1;i<=ll;i++)
{
if(get(a[i].x)!=get(a[i].y)){
ans+=a[i].v;sum++;
int tx=get(a[i].x),ty=get(a[i].y);
// f[tx]=ty;
if(siz[tx]>siz[ty])
f[ty]=tx,siz[tx]+=siz[ty],siz[ty]=0;
else f[tx]=ty,siz[ty]+=siz[tx],siz[tx]=0;
}
}
if(sum<n-1)ans=-1;
printf("%d",ans);
}