首先二分一下答案,然后距离小于答案的点对暴力连边,并查集判断即可。
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<algorithm>
#define eps 1e-5
#define maxn 1010
using namespace std;
int x[maxn],y[maxn];
int f[maxn];
bool vis[maxn];
int n,k;
double dis(int i,int j)
{
return sqrt((double)(x[i]-x[j])*(x[i]-x[j])+(double)(y[i]-y[j])*(y[i]-y[j]));
}
int find(int x)
{
if (f[x]==x) return x;
else return f[x]=find(f[x]);
}
int check(double x)
{
memset(vis,0,sizeof(vis));
for (int i=1;i<=n;i++) f[i]=i;
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
if (i!=j && dis(i,j)<x)
{
int f1=find(i),f2=find(j);
if (f1!=f2) f[f1]=f2;
}
int num=0;
for (int i=1;i<=n;i++)
if (!vis[find(i)]) vis[find(i)]=1,num++;
return num;
}
int main()
{
scanf("%d%d",&n,&k);
for (int i=1;i<=n;i++) scanf("%d%d",&x[i],&y[i]);
double l=0,r=10000000000;
while (r-l>eps)
{
double mid=(l+r)/2.0;
if (check(mid)<k) r=mid;
else l=mid;
}
printf("%.2lf\n",l);
return 0;
}