当前位置: 首页 > news >正文

算法讲解—最小生成树(Kruskal 算法)

算法讲解—最小生成树(Kruskal 算法)

简介

根据度娘的解释我们可以知道,最小生成树(Minimum Spanning Tree, MST)就是:一个有 n n n 个结点的连通图的生成树是原图的极小连通子图,且包含原图中的所有 n n n 个结点,并且有保持图连通的最少的边。

简单点来说就是求最小的连通图,就是从一个点能到达图的任意一点,且花费的代价最小(所有边的权值最小)。

最小生成树问题通常用于网络设计、电路设计等领域,目的是找到连接所有节点的最低成本方式。常见的算法有克鲁斯卡尔算法(Kruskal)和普里姆算法(Prim)等。

Kruskal 算法

要实现最小生成树,最著名的就是 Kruskal 算法。

Kruskal 算法是一种用来求解最小生成树问题的贪心算法。最小生成树问题是指在一个连通带权无向图中找到一个生成树,使得所有边的权重之和最小。

Kruskal 算法的基本思想是从小到大选择边,直到选出 n − 1 n-1 n1 条边为止( n n n 为节点数)。具体步骤如下:

  1. 将图中的所有边按照权重从小到大进行排序。

  2. 初始化一个空的集合 M M M,用来存放最小生成树的边。

  3. 遍历排序后的边,如果当前边的两个端点不在同一个连通分量中,则将这条边加入集合 M M M ,并将两个端点所在的连通分量合并。

  4. 重复步骤 3 3 3,直到集合 M M M 中的边数达到 n − 1 n-1 n1 条,其中 n n n 为节点数。

  5. 最后得到的集合 M M M 就是最小生成树。

Kruskal 算法的时间复杂度主要取决于排序边的时间复杂度,通常使用快速排序等快速的排序算法,因此总的时间复杂度为 O ( E log ⁡ E ) O(E \log E) O(ElogE),其中 E E E 为边数。

需要注意的是,在实际应用中,Kruskal 算法还需要对图进行一些预处理,如可以先对边进行去重、排序等操作,以提高算法的效率。

引用一张百度的图片

代码实现

Python(由 AI 生成)

class DisjointSet:def __init__(self):self.parent = {}self.rank = {}def make_set(self, node):self.parent[node] = nodeself.rank[node] = 0def find_set(self, node):if self.parent[node] != node:self.parent[node] = self.find_set(self.parent[node])return self.parent[node]def union_sets(self, node1, node2):root1 = self.find_set(node1)root2 = self.find_set(node2)if root1 != root2:if self.rank[root1] > self.rank[root2]:self.parent[root2] = root1elif self.rank[root1] < self.rank[root2]:self.parent[root1] = root2else:self.parent[root2] = root1self.rank[root1] += 1def kruskal(edges, n):disjoint_set = DisjointSet()for i in range(n):disjoint_set.make_set(i)edges.sort(key=lambda edge: edge[2])result = []for edge in edges:node1, node2, weight = edgeroot1 = disjoint_set.find_set(node1)root2 = disjoint_set.find_set(node2)if root1 != root2:disjoint_set.union_sets(node1, node2)result.append(edge)return result

C++ (由 AI 生成)

#include <iostream>
#include <vector>
#include <algorithm>using namespace std;struct Edge {int u, v, weight;bool operator<(const Edge& other) const {return weight < other.weight;}
};int findParent(vector<int>& parent, int i) {if (parent[i] == -1) return i;return parent[i] = findParent(parent, parent[i]);
}void kruskal(vector<Edge>& edges, int n) {vector<int> parent(n, -1);int num_edges = 0;int result = 0;sort(edges.begin(), edges.end());for (const auto& edge : edges) {int u_parent = findParent(parent, edge.u);int v_parent = findParent(parent, edge.v);if (u_parent != v_parent) {parent[u_parent] = v_parent;result += edge.weight;num_edges++;if (num_edges == n - 1) break;  // 加上n-1条边即可构成最小生成树}}if (num_edges < n - 1) {cout << "无法构成最小生成树" << endl;} else {cout << "最小生成树的权值总和为: " << result << endl;}
}int main() {int n, m; // n为顶点数,m为边数cin >> n >> m;vector<Edge> edges(m);for (int i = 0; i < m; ++i) {int u, v, weight;cin >> u >> v >> weight;edges[i] = {u, v, weight};}kruskal(edges, n);return 0;
}

洛谷模版题

【洛谷】P3366 【模板】最小生成树

板子代码

#include <bits/stdc++.h>
using namespace std;
int n, m, sum, ans, fa[10005];
struct node {int x, y, z;
}f[200005];
int find(int x) {return x == fa[x] ? x : fa[x] = find(fa[x]);}
bool cmp (node a, node b) {return a.z < b.z;}
int main() {cin >> n >> m;for (int i = 1; i <= n; i ++) {fa[i] = i;}for (int i = 1; i <= m; i ++) {cin >> f[i].x >> f[i].y >> f[i].z;}sort (f + 1, f + m + 1, cmp);	for (int i = 1; i <= m; i ++) {if (find(f[i].x) != find(f[i].y)) {sum ++;fa[find(f[i].y)] = find(f[i].x);ans += f[i].z;	} else continue;if (sum == n - 1) {cout << ans;return 0;}}cout << "orz";return 0;
}

推荐好题

【洛谷】 P1194 买礼物
详细讲解

【洛谷】P1396 营救
详细讲解

【洛谷】P2820 局域网
详细讲解

【洛谷】P2330 SCOI2005 繁忙的都市
详细讲解

【洛谷】P3623 APIO2008 免费道路
详细讲解

参考

  • https://baike.baidu.com/item/%E6%9C%80%E5%B0%8F%E7%94%9F%E6%88%90%E6%A0%91/5223845?fr=ge_ala

  • https://blog.csdn.net/2301_79188764/article/details/142172901

  • https://www.dotcpp.com/course/1061

  • https://baike.baidu.com/item/%E5%85%8B%E9%B2%81%E6%96%AF%E5%8D%A1%E5%B0%94%E7%AE%97%E6%B3%95/4455899?fr=ge_ala

相关文章:

算法讲解—最小生成树(Kruskal 算法)

算法讲解—最小生成树&#xff08;Kruskal 算法&#xff09; 简介 根据度娘的解释我们可以知道&#xff0c;最小生成树(Minimum Spanning Tree, MST)就是&#xff1a;一个有 n n n 个结点的连通图的生成树是原图的极小连通子图&#xff0c;且包含原图中的所有 n n n 个结点…...

掌握 C# 多线程与异步编程

现代应用程序通常需要执行复杂的计算或处理 I/O 操作&#xff0c;这些操作可能会导致主线程阻塞&#xff0c;从而降低用户体验。C# 提供了多线程与异步编程的多种工具&#xff0c;让我们能够高效地并发处理任务。本文将介绍 C# 中的多线程与异步编程&#xff0c;包括 Thread 类…...

Angular 2 用户输入

Angular 2 用户输入 Angular 2 是一个由 Google 维护的开源前端 web 框架,用于构建单页应用程序(SPA)。它以其高效的双向数据绑定、模块化架构和强大的依赖注入系统而闻名。在 Angular 2 应用程序中,处理用户输入是核心功能之一,因为它允许应用程序响应用户的操作。 Ang…...

线程安全的单例模式 | 可重入 | 线程安全 |死锁(理论)

&#x1f308;个人主页&#xff1a; 南桥几晴秋 &#x1f308;C专栏&#xff1a; 南桥谈C &#x1f308;C语言专栏&#xff1a; C语言学习系列 &#x1f308;Linux学习专栏&#xff1a; 南桥谈Linux &#x1f308;数据结构学习专栏&#xff1a; 数据结构杂谈 &#x1f308;数据…...

解决方案:梯度提升树(Gradient Boosting Trees)跟GBDT(Gradient Boosting Decision Trees)有什么区别

文章目录 一、现象二、解决方案梯度提升树&#xff08;GBT&#xff09;GBDT相同点区别 一、现象 在工作中&#xff0c;在机器学习中&#xff0c;时而会听到梯度提升树&#xff08;Gradient Boosting Trees&#xff09;跟GBDT&#xff08;Gradient Boosting Decision Trees&…...

亚马逊国际商品详情API返回值:电商精准营销的关键

亚马逊国际商品详情API&#xff08;Amazon Product Advertising API&#xff09;为开发者提供了一种获取商品信息的方式&#xff0c;这些信息对于电商精准营销至关重要。通过分析API返回的详细数据&#xff0c;商家可以制定更精准的营销策略&#xff0c;提高用户购买转化率。 …...

python爬虫 - 进阶requests模块

&#x1f308;个人主页&#xff1a;https://blog.csdn.net/2401_86688088?typeblog &#x1f525; 系列专栏&#xff1a;https://blog.csdn.net/2401_86688088/category_12797772.html 目录 前言 一、SSL证书问题 &#xff08;一&#xff09;跳过 SSL 证书验证 &#xff0…...

代码随想录 103. 水流问题

103. 水流问题 #include<bits/stdc.h> using namespace std;void dfs(vector<vector<int>>& mp, vector<vector<int>>& visit, int y, int x){if (visit[y][x] 1) return;visit[y][x] 1;if (y > 0){if (mp[y][x] < mp[y - 1][x…...

数据结构-排序1

1.排序的概念 排序&#xff1a;所谓排序&#xff0c;就是使一串记录&#xff0c;按照其中的某个或某些关键字的大小&#xff0c;递增或递减的排列起来的操作。 稳定性&#xff1a;假定在待排序的记录序列中&#xff0c;存在多个具有相同的关键字的记录&#xff0c;若经过排序…...

Springboot 整合 durid

文章目录 Springboot 整合 druiddruid的优势配置参数使用整合 Druid配置数据源配置参数绑定配置参数配置监控页面配置拦截器 Springboot 整合 druid druid的优势 可以很好的监控 DB 池连接 和 SQL 的执行情况可以给数据库密码加密可以很方便的编写JDBC插件 配置参数 使用 整…...

JVM 系列知识体系全面回顾

经过几个月的努力&#xff0c;JVM 知识体系终于梳理完成了。 很早之前也和小伙伴们分享过 JVM 相关的技术知识&#xff0c;再次感谢大家支持和反馈。 最后再次献上 JVM系列文章合集索引&#xff0c;感兴趣的小伙伴可以点击查看。 JVM系列(一) -什么是虚拟机JVM系列(二) -类的…...

crossover软件如何安装程序 及最新图文案张教程

IT之家 2 月 23 日消息&#xff0c;CodeWeavers 近日发布了 CrossOver 24 版本更新&#xff0c;基于近期发布的 Wine 9.0&#xff0c;不仅兼容更多应用和游戏&#xff0c;还初步支持运行 32 位应用程序。 苹果在 macOS Catalina 系统中移除对 32 位软件的支持之后&#xff0c;在…...

Python爬虫之正则表达式于xpath的使用教学及案例

正则表达式 常用的匹配模式 \d # 匹配任意一个数字 \D # 匹配任意一个非数字 \w # 匹配任意一个单词字符&#xff08;数字、字母、下划线&#xff09; \W # 匹配任意一个非单词字符 . # 匹配任意一个字符&#xff08;除了换行符&#xff09; [a-z] # 匹配任意一个小写字母 […...

Jenkins打包,发布,部署

一、概念 Jenkins是一个开源的持续集成工具&#xff0c;主要用于自动构建和测试软件项目&#xff0c;以及监控外部任务的运行。与版本管理工具&#xff08;如SVN&#xff0c;GIT&#xff09;和构建工具&#xff08;如Maven&#xff0c;Ant&#xff0c;Gradle&#xff09;结合使…...

CSS 实现楼梯与小球动画

CSS 实现楼梯与小球动画 效果展示 CSS 知识点 CSS动画使用transform属性使用 页面整体布局 <div class"window"><div class"stair"><span style"--i: 1"></span><span style"--i: 2"></span>…...

sqli-labs less-14post报错注入updatexml

post提交报错注入 闭合方式及注入点 利用hackbar进行注入&#xff0c;构造post语句 unameaaa"passwdbbb&SubmitSubmit 页面报错&#xff0c;根据分析&#xff0c;闭合方式". 确定列数 构造 unameaaa" or 11 # &passwdbbb&SubmitSubmit 确定存在注…...

Python开发环境配置(mac M2)

1. 前言 作为一名程序员&#xff0c;工作中需要使用Python进行编程&#xff0c;甚至因为项目需要还得是不同版本的Python如何手动管理多个版本的Python&#xff0c;如何给Pycharm&#xff08;IDE&#xff09;配置对应的interpreter等&#xff0c;都成为一个 “不熟练工” 的难…...

其他:Python语言绘图合集

文章目录 介绍注意导入数据函数模块画图 介绍 python语言的科研绘图合集 注意 This dataset includes the following (All files are preceded by "Marle_et_al_Nature_AirborneFraction_"):- "Datasheet.xlsx": Excel dataset containing all annual a…...

处理 Vue3 中隐藏元素刷新闪烁问题

一、问题说明 页面刷新&#xff0c;原本隐藏的元素会一闪而过。 效果展示&#xff1a; 页面的导航栏通过路由跳转中携带的 meta 参数控制导航栏的 显示/隐藏&#xff0c;但在实践过程中发现&#xff0c;虽然元素隐藏了&#xff0c;但是刷新页面会出现闪烁的问题。 项目源码&…...

【MySQL】数据目录迁移

一、使用场景 使用该方法一般是数据目录所在磁盘不支持扩展&#xff0c;只能通过新加磁盘来扩展数据目录磁盘空间。通常是Windows服务器&#xff0c;或者是Linux服务器的mysql数据目录的磁盘没有使用lvm。 二、准备工作 1. 新磁盘初始化&#xff0c;达到可使用状态 2. 需要自己…...

利用最小二乘法找圆心和半径

#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …...

简易版抽奖活动的设计技术方案

1.前言 本技术方案旨在设计一套完整且可靠的抽奖活动逻辑,确保抽奖活动能够公平、公正、公开地进行,同时满足高并发访问、数据安全存储与高效处理等需求,为用户提供流畅的抽奖体验,助力业务顺利开展。本方案将涵盖抽奖活动的整体架构设计、核心流程逻辑、关键功能实现以及…...

UDP(Echoserver)

网络命令 Ping 命令 检测网络是否连通 使用方法: ping -c 次数 网址ping -c 3 www.baidu.comnetstat 命令 netstat 是一个用来查看网络状态的重要工具. 语法&#xff1a;netstat [选项] 功能&#xff1a;查看网络状态 常用选项&#xff1a; n 拒绝显示别名&#…...

微服务商城-商品微服务

数据表 CREATE TABLE product (id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 商品id,cateid smallint(6) UNSIGNED NOT NULL DEFAULT 0 COMMENT 类别Id,name varchar(100) NOT NULL DEFAULT COMMENT 商品名称,subtitle varchar(200) NOT NULL DEFAULT COMMENT 商…...

C# 类和继承(抽象类)

抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...

《基于Apache Flink的流处理》笔记

思维导图 1-3 章 4-7章 8-11 章 参考资料 源码&#xff1a; https://github.com/streaming-with-flink 博客 https://flink.apache.org/bloghttps://www.ververica.com/blog 聚会及会议 https://flink-forward.orghttps://www.meetup.com/topics/apache-flink https://n…...

【RockeMQ】第2节|RocketMQ快速实战以及核⼼概念详解(二)

升级Dledger高可用集群 一、主从架构的不足与Dledger的定位 主从架构缺陷 数据备份依赖Slave节点&#xff0c;但无自动故障转移能力&#xff0c;Master宕机后需人工切换&#xff0c;期间消息可能无法读取。Slave仅存储数据&#xff0c;无法主动升级为Master响应请求&#xff…...

Caliper 配置文件解析:config.yaml

Caliper 是一个区块链性能基准测试工具,用于评估不同区块链平台的性能。下面我将详细解释你提供的 fisco-bcos.json 文件结构,并说明它与 config.yaml 文件的关系。 fisco-bcos.json 文件解析 这个文件是针对 FISCO-BCOS 区块链网络的 Caliper 配置文件,主要包含以下几个部…...

Rapidio门铃消息FIFO溢出机制

关于RapidIO门铃消息FIFO的溢出机制及其与中断抖动的关系&#xff0c;以下是深入解析&#xff1a; 门铃FIFO溢出的本质 在RapidIO系统中&#xff0c;门铃消息FIFO是硬件控制器内部的缓冲区&#xff0c;用于临时存储接收到的门铃消息&#xff08;Doorbell Message&#xff09;。…...

Java线上CPU飙高问题排查全指南

一、引言 在Java应用的线上运行环境中&#xff0c;CPU飙高是一个常见且棘手的性能问题。当系统出现CPU飙高时&#xff0c;通常会导致应用响应缓慢&#xff0c;甚至服务不可用&#xff0c;严重影响用户体验和业务运行。因此&#xff0c;掌握一套科学有效的CPU飙高问题排查方法&…...