洛谷 P1991 【无线通讯网】

这道题找到关键点那就是模板题了,代码好写哒~


因为有S个电话,两个电话就可以连通两个块,那是不是我们就可以看做一条无消耗的边,提前连了起来。根据Kruskal的思想,我们每次加入最小的边,直到联通,由于两台电话一条线,所以我们加入的点也就只需要P-S条了,相当于贪心掉了最大需要的边。

O泡代码时间到:

#include 
using namespace std;
struct node{
	int l , r;
	double w;
}; 
node e[2500010];
int k , n , tot , now;
int fa[510];
double ans;
double a[510] , b[510];
double work(int x , int y){
	return sqrt((a[x] - a[y]) * (a[x] - a[y]) + (b[x] - b[y]) * (b[x] - b[y]));
}
int find(int x){
	if(fa[x] == x) return x;
	return fa[x] = find(fa[x]);
}
bool cmp(node x , node y){
	return x.w < y.w;
}
int main(){
	cin >> k >> n;
	for(int i = 1; i <= n; i++) cin >> a[i] >> b[i];
	for(int i = 1; i <= n; i++)
		for(int j = 1; j <= n; j++)
			if(j > i){	//读入一半的边就行了 
				e[++tot].w = work(i , j);
				e[tot].l = i;
				e[tot].r = j;
			}
	for(int i = 1; i <= n; i++) fa[i] = i;
	sort(e + 1 , e + tot + 1 , cmp);
	for(int i = 1; i <= tot; i++){
		if(now == n - k) break;
		int x = find(e[i].l) , y = find(e[i].r);
		if(x == y) continue;
		fa[x] = y;
		ans = e[i].w;
		now++;
	}
	printf("%.2f" , ans);	//注意精度 
	return 0;
}

你可能感兴趣的:(洛谷 P1991 【无线通讯网】)