Prim最小生成树

Prim最小生成树是一个动态的过程,
并不是一次性把所有结点的最小的key都算出来然后一个一个往最小生成树里面加,
而是先选定一个结点,让他最小成为第一个加进去,以此为基础开始循环,更新key的值,
每次都加入当前最小的并且没有被加入的,每一次循环都在更新,直到把所有的都加进去。

代码几乎是抄的,因为我没有写出来…
修改了一些,加了些注释,让输出清楚完整一些,改的有点不像C++了…
修改前的源码是这位博主的:https://blog.csdn.net/I_am_a_winer/article/details/45276643

贴下新的代码:


#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define INF 0x7fffffff

using namespace std;

int Map[110][110], dis[110], vis[110];      
//map就是存两点权值的矩阵,注意:二维数组的下标刚好是两个结点的值。dis相当于书上的key,是不断更新的当前结点相连的边的最小权重,vis记录结点是否已经被访问
int N, M;

void prime(int s) {
	printf("路径\n");

	memset(vis, 0, sizeof(vis));                 //初始化访问的数组都为0

	for (int i = 1; i <= N; i++)            //每个结点的权值都初始化为与1的之间边的权值
		
		dis[i] = Map[1][i];                //权值可以理解成距离,似乎更好理解

	int sum = 0;
	
	vis[s] = s;                        
	
	printf("%d    ", s);

	for (int p = 1; p <= N - 1; p++) {  //进行N-1次循环,加入剩下的N-1个点
		
		int t, Min = INF;

		for (int i = 1; i <= N; i++)

			if (!vis[i] && dis[i]<Min)              //如果没有访问过这个结点并且他的值小于min //寻找集合1-S中到集合S最近的点t
	        
				Min = dis[i], t = i;                //最小值就变成他并且记录他的下标i
		
		sum += Min; vis[t] = 1;         //找到那个当前的最小值之后,把标记他为已经访问,然后再把权值加到路径里面去
	
		printf("%d   ", t);
		
		for (int i = 1; i <= N; i++) 
			
			if (!vis[i] && dis[i]>Map[t][i])      //更新与t相连且在1-S中的点到集合S的距离
			
				dis[i] = Map[t][i];
	}
	printf("\n最小生成树权值:\n");

	cout << sum << endl;
}


int main() {
	int s;
	//freopen("D:\\in.txt","r",stdin);
	printf("输入结点个数:\n");

	while (cin >> N && N) {

		for (int i = 0; i <= N; i++)              //初始化矩阵为最大值
			for (int j = 0; j <= N; j++) 
				Map[i][j] = INF;

		printf("输入边的条数:\n");
		scanf_s("%d", &M);

		printf("输入第一个点:\n");
		scanf_s("%d", &s);
	
		//	M = (N - 1)*N / 2;
		
		printf("输入两点和权重(逗号分隔)\n");
		
		int a, b, c;
		for (int i = 0; i<M; i++) {
			scanf_s("%d,%d,%d", &a, &b, &c);
			Map[a][b] = Map[b][a] = c;                         //注意无向图在给矩阵赋值的时候是双向的
		}
		prime(s);
	}
	return 0;
}

在这里插入图片描述

测试数据来自算法导论,是没有问题的。把abc改成123这样的。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值