剑鱼行动

版权声明:欢迎各位巨佬评论! https://blog.csdn.net/weixin_43346722/article/details/89597352

剑鱼行动

题目

给出N个点的坐标,对它们建立一个最小生成树,代价就是连接它们的路径的长度,现要求总长度最小。

输入

第一行:一个数n,表示有n个点。
第二到n+1行:两个数,表示每一个点的坐标。

输出

总长度,保留两位小数。

输入样例

5
0 0
0 1
1 1
1 0
0.5 0.5

输出样例

2.83

数据范围

N的值在100以内。
坐标值在[-10000,-10000]到[10000,10000]内。

思路

这道题其实就是一道最小生成树
不过两点之间的距离我们要用勾股定理来求出,而且要保留两位小数,然后基本就可以了。

代码

#include<cstdio>
#include<cmath>
#include<algorithm> 
using namespace std;
struct note
{
	int x,y;
	double l;
}a[10001];
struct zb
{
	double x,y;
}b[101];
int n,k,u,f[101];
double answer;
int find(int x)//寻找这个点的根节点
{
	if (f[x]==x) return x;
	return f[x]=find(f[x]);
}
void connect(int x,int y)//连接这两个点
{
	int xx=find(x),yy=find(y);
	if (xx<yy) f[xx]=yy;
	else f[yy]=xx;
}
bool cmp(note x,note y)
{
	return x.l<y.l;
}
int main()
{
	scanf("%d",&n);//读入
	for (int i=1;i<=n;i++)
	{
		f[i]=i;//初始化
		scanf("%lf%lf",&b[i].x,&b[i].y);//读入坐标
	}
	for (int i=1;i<=n;i++)
	for (int j=1;j<=n;j++)
	if (i!=j)
	{
		double l=sqrt(double(b[i].x-b[j].x)*double(b[i].x-b[j].x)+double(b[i].y-b[j].y)*double(b[i].y-b[j].y));
		//通过勾股定理求出两点之间的距离
		a[++k]=(note){i,j,l};//记录
	}
	sort(a+1,a+k+1,cmp);//按边的权值从小到大排序
	for (int i=1;i<=k;i++)
	if (find(a[i].x)!=find(a[i].y))//如果两个点不相连
	{
		u++;//线数加一
		connect(a[i].x,a[i].y);//连接这两个点
		answer+=a[i].l;//答案要加边的权值
		if (u==n-1) break;//如果所有点已经联通则直接退出
	}
	printf("%.2lf",answer);//输出(保留两位小数)
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43346722/article/details/89597352