P4047 [JSOI2010]部落劃分(Kruskal)

P4047 [JSOI2010]部落劃分(Kruskal)

傳送門

思路:最小生成樹,因爲每個部落的距離定義爲每個部落中距離最近的兩個點的距離,所以我們可以建立一個最小生成樹,一個點代表第一個部落,因爲我們要分成kk個部落,所以需要刪去(n1)(k1)=nk(n-1)-(k-1)=n-k條邊,顯然貪心的刪去最小的nkn-k條邊是最優的,所以答案就是第nk+1n-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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章