mst[讲课留档]

最小生成树(Minimum Spanning Tree)

(1)概念

我们知道,是有 n n n个结点, n − 1 n-1 n1条边的无向无环的连通图。

一个连通图的生成树是一个极小的连通子图,它包含图中全部的 n n n个顶点,但只有构成一棵树的 n − 1 n-1 n1条边。

最小生成树就是一个带权图,每个边都有一个边权,一颗生成树的权值是该树边所有边权的和, M S T MST MST就是所有生成树中最小的一个。

(2)Prim算法(遍历点的算法)

普里姆算法在找最小生成树时,将顶点分为两类,一类是在查找的过程中已经包含在生成树中的顶点(假设为 A 类),剩下的为不在生成树中的(假设为 B 类)。

对于给定的连通网,起始状态全部顶点都归为 B 类。在找最小生成树时,选定任意一个顶点作为起始点,并将之从 B 类移至 A 类;然后找出 B 类中到 A 类中的顶点之间权值最小的顶点,将之从 B 类移至 A 类,如此重复,直到 B 类中没有顶点为止。所走过的顶点和边就是该连通图的最小生成树。

请添加图片描述

int dis[N];
int mp[N][N];
bool vis[N];void work() {int n, m;cin >> n >> m;int ans = 0;memset(vis, 0, sizeof vis);memset(mp, 0x3f3f3f3f, sizeof mp);for (int i = 0; i < n; ++i) {int u, v, w;cin >> u >> v >> w;mp[u][v] = w;mp[v][u] = w;}for (int i = 0; i < n; ++i) {dis[i] = 0x3f3f3f3f;}dis[0] = 0;vis[0] = 1;for (int i = 1; i < n; ++i) {dis[i] = min(dis[i], mp[0][i]);}for (int i = 1; i < n; ++i) {//这里的外层循环是循环遍数,与i值无关double minn = 0x3f3f3f3f;int pos = -1;for (int j = 1; j < n; ++j) {//每次循环找出与已排联通块距离最近的点if (!vis[j] && minn > dis[j]) {pos = j;minn = dis[j];}}ans += minn;vis[pos] = 1;for (int j = 0; j < n; ++j) {//刷新未连接点的距离最小值dis[j] = min(dis[j], mp[pos][j]);}}cout << ans << '\n';
}

正确性显然。

复杂度是 O ( n 2 ) O(n^2) O(n2)级别的,但是我们可以使用堆优化降到 O ( n l o g n ) O(nlogn) O(nlogn),之后讲最短路的时候会讲堆优化。

(3)Kruskal算法(遍历边的算法)

克鲁斯卡尔算法(Kruskal)是一种使用贪婪方法的最小生成树算法。 该算法初始将图视为森林,图中的每一个顶点视为一棵单独的树。 一棵树只与它的邻接顶点中权值最小且不违反最小生成树属性(不构成环)的树之间建立连边。

请添加图片描述

利用并查集可以快速实现查找两个点是否已经连接

int n, m;
int f[105];
struct road {int a, b, v;
} arr[305];int find(int a) {if (f[a] == a)return a;elsereturn f[a] = find(f[a]);
}void join(int a, int b) {if (find(a) != find(b))f[find(a)] = find(b);
}bool cmp(road a, road b) {return a.v < b.v;
}void work() {cin >> n >> m;int a, b, c;for (int i = 1; i <= n; ++i) {f[i] = i;}int ans = 0;for (int i = 0; i < m; ++i) {cin >> arr[i].a >> arr[i].b >> arr[i].v;}sort(arr, arr + m, cmp);//先按路的权值排序,如果两点的祖先不是一个就加上然后合并。for (int i = 0; i < m; ++i) {if (find(arr[i].a) != find(arr[i].b)) {ans += arr[i].v;join(arr[i].a, arr[i].b);}}cout << ans << '\n';return 0;
}

正确性证明:

给一带权连通的树一定会有至少一棵生成树,那么这些生成树中间必然会会存在至少一棵最小生成树。

假设 T T T是用 k r u s k a l kruskal kruskal求出来的最小生成树,而 U U U是这个图的最小生成树,要证 U = T U = T U=T
然而如果 T ≠ U T \neq U T=U,那么至少存在一条边在 T T T中,不在 U U U中,假设存在 k k k条边存在 T T T中不存在 U U U中。
接下来进行 k k k次变换:
每次将在 T T T中不在 U U U中的最小的边 f f f拿出来放到 U U U中,那么 U U U中必然形成一条唯一的环路,我们取出这个环路上最小的且不在 T T T中的边 e e e放回到 T T T中,这样的边 e e e一定是存在的,因为之前的 T T T不存在环路(如果 e e e T T T中那么就可能和 f f f形成环路)。

在这里插入图片描述
现在证明 f f f e e e权值的关系:

假设 f < e f < e f<e,那么后来形成的 U U U是权值之和更小了,与 U U U是最小生成树矛盾。 实际上,不可能在 U U U中拿到大于 f f f的边,因为把 f f f拿走后,如果小于 f f f的边都不成立,至少 f f f是一个符合条件的边会被那回。

假设 f > e f > e f>e,那么根据 k r u s k a l kruskal kruskal的做法, e e e是在 f f f之前被取出来的边但是被舍弃了,一定是因为 e e e和比 e e e小的边形成了环路,而比 e e e小的边都是存在 U U U中的,而 e e e和这些边并没有形成环路,于假设矛盾。

于是 f f f一定和 e e e相等的, k k k次变换后, T T T U U U的权值之和是相等的。

最小生成树的值也是相等的。

复杂度是 O ( n l o g n ) O(nlogn) O(nlogn)级别的,一般有mst就用这个。

int f[N];
struct road {int a, b, v;
} arr[N];
int tot = 0;int find(int a) {if (f[a] == a)  return a;return f[a] = find(f[a]);
}void join(int a, int b) {if (find(a) != find(b)) f[find(a)] = find(b);
}bool cmp(road a, road b) {return a.v < b.v;
}void work() {int a, b;cin >> a >> b;for (int i = 1; i <= b; ++i) {f[i] = i;arr[i] = {0, i, a};}tot = b;for (int i = 1; i <= b; ++i) {for (int j = 1; j <= b; ++j) {int x; cin >> x;if (x == 0) continue;else arr[++tot] = {i, j, x};}}ll ans = 0;sort(arr + 1, arr + 1 + tot, cmp);for (int i = 1; i <= tot; ++i) {if (find(arr[i].a) != find(arr[i].b)) {ans += arr[i].v;join(arr[i].a, arr[i].b);b--;}if (b == 0) break;}cout << ans << '\n';
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/366186.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【C++】C++指针在线程中调用与受保护内存空间读取方法

引言 在C的多线程编程中&#xff0c;正确地管理内存和同步访问是确保程序稳定性和安全性的关键。特别是当涉及到指针在线程中的调用时&#xff0c;对受保护内存空间的访问必须谨慎处理&#xff0c;以防止数据竞争、死锁和内存损坏等问题。本文将详细探讨C指针在线程中调用时如何…

【stm32】大一上学期笔记复制

砌墙单片机 外设是什么&#xff1f; ipage 8 nx轴 128 X0-127 y0-63 PWM脉冲宽度调制 PWM脉冲宽度调制 2023年10月13日 基本特性&#xff1a;脉冲宽度调制PWM是一种对模拟信号进行数字编码的方法。广泛引用于电机控制&#xff0c;灯光的亮度调节&#xff0c;功率控制等领域…

人工智能--目标检测

欢迎来到 Papicatch的博客 文章目录 &#x1f349;引言 &#x1f349;概述 &#x1f348;目标检测的主要流程通常包括以下几个步骤 &#x1f34d;数据采集 &#x1f34d;数据预处理 &#x1f34d;特征提取 &#x1f34d;目标定位 &#x1f34d;目标分类 &#x1f348;…

调度器APScheduler定时执行任务

APScheduler&#xff08;Advanced Python Scheduler&#xff09;是一个Python库&#xff0c;用于调度任务&#xff0c;使其在预定的时间间隔或特定时间点执行。它支持多种调度方式&#xff0c;包括定时&#xff08;interval&#xff09;、日期&#xff08;date&#xff09;和Cr…

使用Git从Github上克隆仓库,修改并提交修改

前言 本次任务主要是进行github提交修改的操作练习实践&#xff0c;本文章是对实践过程以及遇到的问题进行的一个记录。 在此之前&#xff0c;我已经简单使用过github&#xff0c;Git之前已经下好了&#xff0c;所以就省略一些步骤。 步骤记录 注册github账号&#xff0c;gi…

C++ | Leetcode C++题解之第208题实现Trie(前缀树)

题目&#xff1a; 题解&#xff1a; class Trie { private:vector<Trie*> children;bool isEnd;Trie* searchPrefix(string prefix) {Trie* node this;for (char ch : prefix) {ch - a;if (node->children[ch] nullptr) {return nullptr;}node node->children[…

华为OD机试 - 表演赛游戏分组 - 动态规划(Java 2024 D卷 200分)

华为OD机试 2024D卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试&#xff08;JAVA&#xff09;真题&#xff08;D卷C卷A卷B卷&#xff09;》。 刷的越多&#xff0c;抽中的概率越大&#xff0c;每一题都有详细的答题思路、详细的代码注释、样例测…

React-Redux

Redux 通常用于管理 React 应用程序的状态&#xff0c;特别是在大型和复杂的应用程序中。 在 React 应用程序中&#xff0c;组件的状态通常由组件自身管理。然而&#xff0c;当应用程序变得复杂时&#xff0c;状态管理可能会变得困难&#xff0c;因为需要在多个组件之间共享和同…

基于STM32的温湿度检测TFT屏幕proteus恒温控制仿真系统

一、引言 本文介绍了一个基于STM32的恒温控制箱检测系统&#xff0c;该系统通过DHT11温湿度传感器采集环境中的温湿度数据&#xff0c;并利用TFT LCD屏幕进行实时显示。通过按键切换页面显示&#xff0c;通过按键切换实现恒温控制箱的恒温控制。为了验证系统的可靠性和稳定性&…

电影交流平台小程序的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;电影类型管理&#xff0c;留言反馈管理&#xff0c;电影中心管理&#xff0c;系统管理 微信端账号功能包括&#xff1a;系统首页&#xff0c;电影中心&#xff0c;留言反馈 开发系统&#xff1a;Window…

PAI3D: Painting Adaptive Instance-Prior for 3D Object Detection论文讲解

PAI3D: Painting Adaptive Instance-Prior for 3D Object Detection论文讲解 1. 引言2. PAI3D框架2.1 Instance Painter2.2 Adaptive Projection Refiner2.3 Fine-granular Detection Head 3. 实验结果3.1 消融实验 1. 引言 3D目标检测对于自动驾驶来说是一个非常重要的模块&a…

昇思25天学习打卡营第14天|ResNet50迁移学习

学AI还能赢奖品&#xff1f;每天30分钟&#xff0c;25天打通AI任督二脉 (qq.com) 在实际应用场景中&#xff0c;由于训练数据集不足&#xff0c;所以很少有人会从头开始训练整个网络。普遍的做法是&#xff0c;在一个非常大的基础数据集上训练得到一个预训练模型&#xff0c;然…

Vue3学习(二)

回顾 DOM原生事件event对象 当事件发生时&#xff0c;浏览器会创建一个event对象&#xff0c;并将其作为参数传递给事件处理函数。这个对象包含了事件的详细信息&#xff0c;比如&#xff1a; type&#xff1a;事件的类型&#xff08;如 click&#xff09;target&#xff1a…

微信小程序毕业设计-英语互助系统项目开发实战(附源码+论文)

大家好&#xff01;我是程序猿老A&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f49e;当前专栏&#xff1a;微信小程序毕业设计 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; &#x1f380; Python毕业设计…

31 - 最新2024版SpringCloud学习记录 - 关于cloud各种组件的停更/升级/替换

有子曰&#xff1a;“其为人也孝弟&#xff0c;而好犯上者&#xff0c;鲜矣&#xff1b;不好犯上&#xff0c;而好作乱者&#xff0c;未之有也。君子务本&#xff0c;本立而道生。孝弟也者&#xff0c;其为仁之本与&#xff1f;” 几种常用的SpringCloud组件 黑色&#xff1a;…

继承QAbstractListModel,结合QListView

这里想要写一个QAbstractListModel的子类&#xff0c;学习一下如何实例化QAbstractListModel。 QAbstractListModel子类化-CSDN博客 QVariant与自定义类型互转之奇巧淫技_qt 类型转 qvariant-CSDN博客 #pragma once#include <QStyledItemDelegate> #include <qmeta…

【windows|012】光猫、路由器、交换机详解

&#x1f341;博主简介&#xff1a; &#x1f3c5;云计算领域优质创作者 &#x1f3c5;2022年CSDN新星计划python赛道第一名 &#x1f3c5;2022年CSDN原力计划优质作者 ​ &#x1f3c5;阿里云ACE认证高级工程师 ​ &#x1f3c5;阿里云开发者社区专家博主 &#x1f48a;交流社…

51单片机-让一个LED灯闪烁、流水灯(涉及:设置单片机的延迟函数)

目录 设置单片机的延迟&#xff08;睡眠&#xff09;函数查看单片机的时钟频率设置系统频率、定时长度、指令集 完整代码生成HEX文件下载HEX文件到单片机流水灯代码 设置单片机的延迟&#xff08;睡眠&#xff09;函数 查看单片机的时钟频率 检测前单片机必须连接电脑并打开&…

AI与EHS管理结合:融合创新,赋能绿色安全生产

随着科技的不断进步&#xff0c;人工智能AI已经在我们的日常生活中扮演了重要角色。在环保、健康和安全这个重要领域&#xff0c;也就是我们常说的EHS管理中&#xff0c;AI也正发挥着神奇的作用。 咱们知道&#xff0c;一个公司要想好好运转&#xff0c;确保工人安全、保护环境…

万字长文|下一代系统内存数据加速接口SDXI解读

本文内容分为5章节&#xff0c;总计10535字&#xff0c;内容较多&#xff0c;建议先收藏&#xff01; 1.SDXI技术产生的背景 2.SDXI相比DMA的优势 3.SDXI实现原理与架构 3.1 描述符环原理解读 3.2 上下文管理介绍 3.3 AKey与RKey解读 3.4 错误日志和状态管理 3.5 跨Function访…