P4047 [JSOI2010]部落划分(Kruskal)

P4047 [JSOI2010]部落划分(Kruskal)

传送门

思路:最小生成树,因为每个部落的距离定义为每个部落中距离最近的两个点的距离,所以我们可以建立一个最小生成树,一个点代表第一个部落,因为我们要分成 k k 个部落,所以需要删去 ( n 1 ) ( k 1 ) = n k (n-1)-(k-1)=n-k 条边,显然贪心的删去最小的 n k n-k 条边是最优的,所以答案就是第 n k + 1 n-k+1 条边。

#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;
}

猜你喜欢

转载自blog.csdn.net/weixin_45750972/article/details/106956490