快速解决克鲁斯卡尔和普里姆算法--C++实现(CSP通过)

关于此算法的思想. 具体可以参照
最小生成树视频演示(bilibili上的)

此视频演示是我的头号参照, 大量文字叙述算法只会帮倒忙, 必要部分进行画图陈述

克鲁斯卡尔算法(有向图形式):

先将其封装为一个个的方法, 方便代码重用

/*
 从上至下的方法作用:
 */
int getIndexOfRepresentative(const int index);
// 递归获取该编号节点的根节点索引
void merge(const int index1, const int index2);
// index1编号的集合与index2的集合合并, index2的根节点为合并后的树的根节点
bool isLoop(const int index1, const int index2);
// 判断要连接的两点是否会构成回路

方法示例:
getIndexOfRepresentative(1) = 4,
对getIndexOfRepresentative(3) = 4, getIndexOfRepresentative(7) = 4也是如此
在这里插入图片描述在这里插入图片描述首先, 我们先得有存储右侧edge的物品, 这个时候
先起一个定义 边的结构体!

struct edge {
   
	int begin;
	int end;
	int len;
};

至于输入, 排序代码放在最后. 现在, 我们假定已经做好了排序, 完成了图中所示的结构, 那么接下来继续下一步

N

个结点,

M

条给定的无向边
我们先定义好
totalLength, 用于存放路径的总长度
addedEdges用于存放已经加入的边数
我们依据规则, 便能写出如下代码:

	int N, M;
	int totalLength = 0;
	int addedEdges = 0;

	cin >> N >> M;
	edge *edges = new edge[M];
	...
	...
	...
	int i = 0;
	while (i != M)
	{
   
		if (!(isLoop(edges[i].begin, edges[i].end)))
		{
   
			merge(edges[i].begin, edges[i].end);
			addedEdges++;
			totalLength += edges[i].len;
			cout << edges[i].begin << " -> " << edges[i].end
				 << "  len:" << edges[i].len << endl;
			if (addedEdges == (N - 1)) {
    cout << totalLength << endl; return 0; }

		}
		i++;
	}

从edges数组中

取一条最短的边, 判断加入后是否会构成回路, 否, 则将第一个集合与第二个连接起来, addedEdges自增一次, totalLength增加一次==
如图. 将索引为

0 4

的结点连接起来时
在这里插入图片描述我们先判断是否构成回路, 没有构成回路, 进行下一步.
先将0 指向 4, 而 4 指向 6这个根节点
为了让所有结点最终都指向6
需要对索引0往回找, 直到找到根节点1

在这里插入图片描述那么修改顺序如下:
1 —> 1 修改为 1 —> 5
5 —> 1 修改为 5 —> 0
0 —> 5 修改为 0 —> 4
(递归)
在这里插入图片描述至此, 完成了连接.
(3是指向根节点1的, 所以1指向改变, 3随之改变)

#include<iostream>
#include<algorithm>

struct edge {
   
	int begin;
	int end;
	int len;
};

static int nodes[5000];

/*
 从上至下的方法作用:
 递归获取该编号节点的根节点索引
 index1编号的集合与index2的集合合并, index2的根节点为合并后的树的根节点
 判断要连接的两点是否会构成回路
 */
int getIndexOfRepresentative(const int index);
void merge(const int index1, const int index2);
bool isLoop(const int index1, const int index2);
bool compare(edge e1, edge e2) {
   
	return e1.len < e2.len;
}

int main(void) {
   
	using namespace std
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值