通电
链接:
https://www.lanqiao.cn/problems/162/learning/
来源:
蓝桥云课
思路:
运用并差集,先把每一个的x,y,h用公式求出每一个村庄到其他村庄的距离,再把距离排序,优先取最小的。
ps:公式题目上的有误,应该是sqrt((x1-x2)2+(y1-y2)2)+(h1-h2)2
#include<bits/stdc++.h>
using namespace std;
int fa[1010];
double ans;
struct Edge{
int x , y ;double z;
// 重载小于号
bool operator < (const Edge& b){
// 返回真的话,就把当前这个结构体放在b之前
// 返回假的话,就把当前这个结构体放在b之后
return z < b.z;
}
}a[500100];
struct Node{
double x , y ,h ;
}p[1010];
int getf(int x){//寻找每一个村庄的祖节点,并把它路径上的所有村庄优化
if(x == fa[x]) return x;
return fa[x] = getf(fa[x]);
}
void mer( int i ){
int fx = getf(a[i].x),fy =getf(a[i].y);//寻找每一个村庄的祖节点
if(fx == fy) return ;//如果是同一个祖节点则不要这条路线
ans +=a[i].z;//累加
fa[fy] =fx;//更换fy的祖节点
return ;
}
int main()
{
int n , m; cin >> m;
for(int i = 1 ; i <= m ; i++){
fa[i]=i;
}
for(int i = 1 ; i <=m ;i++)
cin >>p[i].x >> p[i].y >> p[i].h;
int k=1;
for(int i = 1 ; i<= m ; i++){
for(int j = i+1 ; j <= m ;j++,k++){//记录每一个村庄到其他的村庄
a[k].x = i;
a[k].y = j;
a[k].z=sqrt((p[i].x-p[j].x)*(p[i].x-p[j].x)+(p[i].y-p[j].y)*(p[i].y-p[j].y))+(p[i].h-p[j].h)*(p[i].h-p[j].h);//题目公式
}
}
sort(a +1 , a + k );//排序
for(int i = 1 ;i < k ;i++){
mer(i);
}
printf("%.2lf",ans);
return 0;
}