最小生成树----prim算法

该代码示例展示了使用C++实现Prim算法来找到图的最小生成树。程序首先初始化节点和边的值,然后通过不断寻找未访问节点中与树中节点距离最近的节点,更新距离并添加到树中,直至构建完整个最小生成树。算法在二维坐标系中计算两点之间的欧几里得距离作为边的权重。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#define _CRT_SECURE_NO_WARNINGS 1
//prim算法,最小生成树
/*
* 每次选择离树最近的一个并且未被访问的点,然后
* 更新与此点相邻的且未被访问的点的值
*/
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
typedef struct node
{
	int x;
	int y;
}NODE;
NODE node[105];
double a[105][105];  //记录边的值  ,第i个点与第j个点间的距离
bool visit[105];  //是否访问过
double dist[1005]; //此节点最小的连接距离
int n;
double prim();
int main(void)
{
	//初始化
	
	for (int i = 0; i < 105; i++)
	{
		visit[i] = false;
		dist[i] = 9999999;
	}
	//输入节点个数与坐标
	cin >> n;
	for (int i = 1; i <= n; i++)
		cin >> node[i].x >> node[i].y;

	//(初始化)更新边的值
	for (int i = 1; i <= n; i++)
		for (int j = i + 1; j <= n; j++)
			a[i][j] = a[j][i] = sqrt(pow(node[i].x - node[j].x, 2) + pow(node[i].y - node[j].y, 2));


	//测试图是否建立正确
	/*for (int i = 1; i <= n; i++)
	{
		for (int j = 1; j <= n; j++)
			cout << a[i][j] << ' ';
		cout << "\n";
	}*/

	printf("%.2lf", prim());
	return 0;
}


//dist[1]置为0,代表从此开始,或者是说目前树只有此一个节点,故一定从此开始
//while循环n次,代表每次都能选出一个点
//第一个for循环是为了找到离树最近的一个并且未被访问的点
//sum加上这个最小值,然后这个点标记为访问过
/*  循环更新与此点相连的点的dist距离,这里更新dist的同时说明第i个节点与树相连
然后上面一个循环中,未更新的点是一个最大值,更新过的点修改了,所以也间接表示了
与树相连的点*/
double prim()
{
	double sum = 0;
	int t = n;
	int temp = 1;
	dist[temp] = 0;

	//找n次,n个点全部都修改到
	while (t--)  
	{
		temp = 0;
		//循环找到离上一个点最近的点
		for (int i = 1; i <= n; i++)
		{
			if (!visit[i] && (temp == 0 || dist[i] < dist[temp]))
				temp = i;
		}

		//结果加上这个找到的最小的权值
		sum += dist[temp];

		//状态修改为修改过,下次不再修改
		visit[temp] = true;

		//更新权值
		for (int i = 1; i <= n; i++)
			if (!visit[i])
				dist[i] = min(dist[i], a[temp][i]);
	}

	return sum;
}

注意边的值的刷新,可能存在重复边;注意提前退出若无法全部连通 

#include<iostream>
#include<algorithm>
using namespace std;
int a[5005][5005];
int dist[5005];
bool visit[5005];
int n, m;
int prim();
int main(void)
{
	cin >> n >> m;
	for (int i = 0; i < 5005; i++)
		for (int j = 0; j < 5005; j++)
			a[i][j] = 0x3f3f3f3f;
	for (int i = 0; i < 5005; i++)
	{
		dist[i] = 0x3f3f3f3f;
		visit[i] = false;
	}

	int x, y, z;
	for (int i = 1; i <= m; i++)
	{
		cin >> x >> y >> z;
		if (z < a[x][y]) a[x][y] = a[y][x] = z;
	}

	int sum=prim();

	if (sum >= 0x3f3f3f3f) cout << "orz";
	else cout << sum;

	return 0;
}

int prim()
{
	dist[1] = 0;
	int temp;
	int t = n;
	int sum = 0;
	while (t--)
	{
		temp = 0;
		for (int i = 1; i <= n; i++)
		{
			if (!visit[i] && (temp == 0 || dist[i] < dist[temp]))
				temp = i;
		}

		if (dist[temp] == 0x3f3f3f3f) return dist[temp];

		visit[temp] = true;
		sum += dist[temp];

		for (int i = 1; i <= n; i++)
		{
			if (!visit[i]) dist[i] = min(dist[i], a[temp][i]);
		}
	}
	return sum;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值