题目大意:给出n个点的坐标,求出将这些点相连,这种连接方式使得所有线段长度和最小,求这个长度和为多少?
其实这道题,比最小生成树的求解多了一个步骤,因为给的是一系列的点,并不像之前的题目给的是一系列的边,我只需要将边权值排序然后kruskal就行,这道题我需要利用一个结构体存储那些输入的点,然后在求解。
#include<iostream>
#include<algorithm>
#include<cmath>
#include<iomanip>
using namespace std;
int parent[101];
int findroot(int x)
{
if (parent[x] != x)
parent[x] = findroot(parent[x]);
return parent[x];
}
struct edge{
int a, b;
double cost;
bool operator <(const edge &a)const{
return cost < a.cost;
}
}e[6000];
struct point{
double x, y;//点的结构体,表示点坐标的x和y
double getdistance(const point &a){//计算点之间的距离
double tmp = (x - a.x)*(x - a.x) + (y - a.y)*(y - a.y);
return sqrt(tmp);
}
}p[101];
int main()
{
int n;
while (cin >> n)
{
for (int i = 0; i < n; i++)
{
cin >> p[i].x >> p[i].y;
}
int size = 0;//统计边的总数
for (int i = 0; i < n; i++)
{
for (int j = i + 1; j < n; j++)
{
e[size].a = i;//边的两个顶点的编号
e[size].b = j;
e[size].cost = p[i].getdistance(p[j]);//边权值为两点之间的长度
size++;
}
}
sort(e, e + size);//同样的先按cost的递增次序排序
for (int i = 0; i < n; i++)
{//对每一个节点定义为孤立的集合,以自己为根节点,并查集的知识!
parent[i] = i;
}
double ans = 0;
for (int i = 0; i < size; i++)
{
int a = findroot(e[i].a);
int b = findroot(e[i].b);
if (a != b)
{
parent[a] = b;
ans += e[i].cost;
}
}
cout << fixed << setprecision(2) << ans << endl;//精度2
}
return 0;
}