P4047 [JSOI2010]部落划分(Kruskal)
思路:最小生成树,因为每个部落的距离定义为每个部落中距离最近的两个点的距离,所以我们可以建立一个最小生成树,一个点代表第一个部落,因为我们要分成 个部落,所以需要删去 条边,显然贪心的删去最小的 条边是最优的,所以答案就是第 条边。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e3+5,M=1e6+5,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a) memset(a,0,sizeof a)
#define lx x<<1
#define rx x<<1|1
#define reg register
#define PII pair<int,int>
#define fi first
#define se second
int n,k;
struct node{
int u,v;
double d;
bool operator<(const node& no)const{
return d<no.d;
}
}a[M];
int s[N],x[N],y[N];
int find(int x){
if(s[x]!=x) s[x]=find(s[x]);
return s[x];
}
int main(){
scanf("%d%d",&n,&k);
int id=0,cnt=0;
for(int i=1;i<=n;i++){
scanf("%d%d",&x[i],&y[i]);
for(int j=1;j<i;j++)
a[++id].u=i,a[id].v=j,a[id].d=hypot(x[i]-x[j],y[i]-y[j]);
s[i]=i;
}
sort(a+1,a+id+1);
double ans=0;
for(int i=1;i<=id;i++){
int fa=find(a[i].u),fb=find(a[i].v);
if(fa!=fb){
s[fa]=fb;
cnt++;
ans=a[i].d;
}
if(cnt==n-k+1) break;
}
printf("%.2lf\n",ans);
return 0;
}