神奇的最小生成树题😀
n^2枚举每一个点,计算出每两点之间的距离
因为没合并一次,就会减少一个部落,所以我们需要合并n-k次
根据贪心的思想,每次我们需要挑出距离最近的两个点合并,否则答案就会变小
所以我们预先排个序,然后每次从小到大找没有连接起来的点,合并即可
是不是特别像kruskal
所以直接跑kruskal模板,找出n-k条边即可,最后输出下一条没有合并的边权,也就是最小距离
#include <bits/stdc++.h>
#include<cstdio>
using namespace std;
int n,m;
int x[1001000],y[1000100];
struct edge{
int a,b;
double c;
}e[2001000];
double dis(int x,int y,int x1,int y1){
return sqrt((x-x1)*(x-x1)+(y-y1)*(y-y1));
}
bool cmp(edge a,edge b){
return a.c<b.c;
}
int fa[1001000];
int get(int x){
if(fa[x]==x)return x;
return fa[x]=get(fa[x]);
}
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>x[i]>>y[i];
fa[i]=i;
}
int cnt=0;
for(int i=1;i<=n;i++){
for(int j=i+1;j<=n;j++){
e[++cnt].a=i;
e[cnt].b=j;
e[cnt].c=dis(x[i],y[i],x[j],y[j]);
}
}
sort(e+1,e+cnt+1,cmp);
int tot=0;
for(int i=1;i<=cnt;i++){
//cout<<e[i].a<<" "<<e[i].b<<" "<<e[i].c<<endl;
int A=get(e[i].a),B=get(e[i].b);
if(A!=B){
tot++;
fa[A]=B;
}
if(tot==n-m+1){
printf("%.2lf",e[i].c);
return 0;
}
}
return 0;
}