前言
本篇承接最小生成树(一),下面给出使用点集判定的最小生成树。
题目传送门:Freckles
题目分析
本体大意是给出了所有点的坐标,然后求一棵最小生成树。
这就相当于是说,这是一个完全图,因此我们就会利用到上一篇所讲的构建点集,然后我们根据点集构建边的集合。将问题转化为上一篇的最小生成树的问题。
注意点:这里边的数量需要重新设置变量,不能使用节点变量n进行遍历。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <string>
#include <algorithm>
#include <cmath>
#define N 6000
using namespace std;
//最小生成树,自己建图
struct Dot{ //点集
float x;
float y;
}dot[N];
struct Edge{ //边集
int a;
int b;
float length;
bool operator <(const Edge &B)const{
return length<B.length;
}
}edge[N];
int Tree[N]; //并查集
int findRoot(int x){ //寻根
if(Tree[x]==-1)
return x;
else{
int root=findRoot(Tree[x]);
Tree[x]=root;
return root;
}
}
int main(){
//freopen("test.txt","r",stdin);
int n;
while(scanf("%d",&n)!=EOF){
memset(Tree,-1,sizeof(Tree));
memset(edge,0,sizeof(edge));
memset(dot,0,sizeof(dot));
for(int i=1;i<=n;i++){
scanf("%f%f",&dot[i].x,&dot[i].y);
}
//计算边长
int edgeNo=1;
for(int i=1;i<=n;i++){
for(int j=i+1;j<=n;j++){
edge[edgeNo].a=i;
edge[edgeNo].b=j;
edge[edgeNo].length=sqrt(
pow((dot[i].x-dot[j].x),2)+pow((dot[i].y-dot[j].y),2)
);
edgeNo++;
}
}
sort(edge,edge+edgeNo);
float re=0;
for(int i=1;i<=edgeNo;i++){
int roota=findRoot(edge[i].a);
int rootb=findRoot(edge[i].b);
if(roota!=rootb){
Tree[roota]=rootb;
re+=edge[i].length;
}
}
printf("%.2f\n",re);
}
return 0;
}