算法与数据结构--最小生成树算法

一.应用的场景

类似于这种最小成本问题,实际上就是计算加权图把所有点连起来权重之和最小值的时候是怎么连接的。类似的问题还有最短耗时之类的问题。

二.最小生成树的定义

生成树:
图的生成树是它的一颗含有其所有顶点无环连通子图。
【简单说就是所有顶点连接在一起,并且没有环。
因此有n个顶点,n-1的边】
最小生成树:
所有生成树中权值(树中所有边的权重之和)最小的生成树。

解决之类问题实际上就是求出最小生成树,并计算它的权值之和。

三.如何构建最小生成树

目前有两种经典的生成最小生成树的算法,Prim算法和Kruskal算法。两种算法都是基于贪婪算法的思想。

1.Kruskal算法

【1】将所有边按照权值从小到大进行排序。
【2】依次取出每条边,如果边的两个节点分别位于两棵树上,则将这两棵树合并成为一棵树;如果两个节点位于同一棵树上,则忽略这条边。
【3】等到所有的边都遍历结束之后,如果所有的生成树可以合并成一棵生成树,那么它就是我们需要寻找的最小生成树,反之则没有最小生成树。

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

// 结构体表示一条边
struct Edge {
    int src, dest, weight;//起点,终点,权值 
};

// 结构体表示并查集
struct DisjointSet {
	//parent 数组存储每个元素的父节点,rank 数组存储每个集合的秩。
    vector<int> parent, rank;
    
    // 构造函数,初始化并查集
    DisjointSet(int n) {
        parent.resize(n);
        rank.resize(n, 0);
        
        // 初始化每个元素为一个独立的集合,父节点指向自身
        for (int i = 0; i < n; i++) {
            parent[i] = i;
        }
    }
    
    // 查找一个元素所属的集合,使用路径压缩优化
    int find(int x) {
        if (parent[x] != x) {
            parent[x] = find(parent[x]); // 路径压缩
        }
        return parent[x];
    }
    
    // 合并两个集合,使用秩优化
    void unionSets(int x, int y) {
        int xRoot = find(x);
        int yRoot = find(y);
        
        if (rank[xRoot] < rank[yRoot]) {
            parent[xRoot] = yRoot;
        } else if (rank[xRoot] > rank[yRoot]) {
            parent[yRoot] = xRoot;
        } else {
            parent[yRoot] = xRoot;
            rank[xRoot]++;
        }
    }
};

// 比较函数,用于对边按权值进行排序
bool compareEdges(const Edge& a, const Edge& b) {
    return a.weight < b.weight;
}

// 使用Kruskal算法求解最小生成树
vector<Edge> kruskalMST(vector<Edge>& edges, int numVertices) {
    // 对边按权值进行排序
    sort(edges.begin(), edges.end(), compareEdges);
    
    vector<Edge> result;
    DisjointSet ds(numVertices);
    
    for (const Edge& edge : edges) {
        int srcParent = ds.find(edge.src);
        int destParent = ds.find(edge.dest);
        
        // 如果加入这条边不会形成环路,则将它加入最小生成树
        if (srcParent != destParent) {
            result.push_back(edge);
            ds.unionSets(srcParent, destParent);
        }
    }
    
    return result;
}

// 打印最小生成树的边集
void printMST(const vector<Edge>& mst) {
    cout << "最小生成树:" << endl;
    for (const Edge& edge : mst) {
        cout << edge.src << " -- " << edge.dest << " : " << edge.weight << endl;
    }
}

int main() {
    int numVertices, numEdges;
    cout << "请输入顶点数:";
    cin >> numVertices;
    cout << "请输入边数:";
    cin >> numEdges;
    
    vector<Edge> edges(numEdges);
    
    cout << "请输入每条边的起点、终点和权值:" << endl;
    for (int i = 0; i < numEdges; i++) {
        cin >> edges[i].src >> edges[i].dest >> edges[i].weight;
    }
    
    vector<Edge> mst = kruskalMST(edges, numVertices);
    
    printMST(mst);
    
    return 0;
}

2.Prim算法

思路:

最优布线问题 题解_学校有 n 台计算机,为了方便数据传输,现要将它们用数据线连接起来。两台计算机被-CSDN博客

代码:

#include <iostream>
#include <vector>
#include <queue>
using namespace std;

const int INF = 1e9; // 定义无穷大

// 表示图的邻接矩阵
vector<vector<int>> graph;

// 使用Prim算法生成最小生成树
void prim(int n)
{
    vector<int> dist(n, INF); // 存储顶点到最小生成树的距离
    vector<bool> visited(n, false); // 记录顶点是否被访问过
    priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq; // 小顶堆

    int src = 0; // 从顶点0开始生成最小生成树
    dist[src] = 0;
    pq.push(make_pair(0, src));

    while (!pq.empty())
    {
        int u = pq.top().second;
        pq.pop();
        visited[u] = true;

        for (int v = 0; v < n; ++v)
        {
            if (graph[u][v] != 0 && !visited[v] && graph[u][v] < dist[v])
            {
                dist[v] = graph[u][v];
                pq.push(make_pair(dist[v], v));
            }
        }
    }

    cout << "边\t权值" << endl;
    for (int i = 1; i < n; ++i)
    {
        cout << i << " - " << i + 1 << "\t" << dist[i] << endl;
    }
}

int main()
{
    int n; // 顶点数量
    cout << "请输入顶点数量: ";
    cin >> n;

    // 初始化邻接矩阵
    graph.resize(n, vector<int>(n));
    cout << "请输入邻接矩阵:" << endl;
    for (int i = 0; i < n; ++i)
    {
        for (int j = 0; j < n; ++j)
        {
            cin >> graph[i][j];
        }
    }

    prim(n);

    return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

作业帮基于 DolphinScheduler 的数据开发平台实践

摘要 随着任务数量、任务类型需求不断增长&#xff0c;对我们的数据开发平台提出了更高的要求。本文主要分享我们将调度引擎升级到 Apache DolphinScheduler 的实践经验&#xff0c;以及对数据开发平台的一些思考。 1. 背景 首先介绍下我们的大数据平台架构&#xff1a; 数据…

在vue3+vite中使用svg-sprite-loader,antdv修改菜单icon

1. 安装 npm install vite-plugin-svg-icons -D 2. 在vite.config.js的plugins中添加配置项 import { createSvgIconsPlugin } from vite-plugin-svg-icons;createSvgIconsPlugin({iconDirs: [resolve(process.cwd(), src/components/svgIcon/svg)], // icon存放的目录&…

【Emgu.CV教程】4.4、无缝融合应用之TextureFlattening()纹理扁平化

这是无缝融合应用的最后一篇&#xff0c;TextureFlattening()函数&#xff0c;专门用于对图像指定部位进行纹理扁平化的。这个功能现在讲起来有点太早了&#xff0c;应该放到《图像的空间滤波--平滑》这一章节中才合适。因为它就是用Sobel算子进行平滑&#xff0c;也就是在保留…

API(Date类,SimpleDateFormat类,Calendar类,JDK8时间相关类,包装类,算法小题)

文章目录 【常用API】今日内容教学目标 第一章 Date类1.1 Date概述1.2 Date常用方法 第二章 SimpleDateFormat类2.1 构造方法2.2 格式规则2.3 常用方法2.4 练习1(初恋女友的出生日期)2.5 练习2(秒杀活动) 第三章 Calendar类3.1 概述3.2 常用方法3.3 get方法示例3.4 set方法示例…

EI级 | Matlab实现VMD-TCN-LSTM变分模态分解结合时间卷积长短期记忆神经网络多变量光伏功率时间序列预测

EI级 | Matlab实现VMD-TCN-LSTM变分模态分解结合时间卷积长短期记忆神经网络多变量光伏功率时间序列预测 目录 EI级 | Matlab实现VMD-TCN-LSTM变分模态分解结合时间卷积长短期记忆神经网络多变量光伏功率时间序列预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 1.【E…

CSS3实现轮播效果

在我们不使用JS的情况下&#xff0c;是否也可以实现轮播功能呢&#xff1f; 答应是可以的 上代码&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>轮播</title><style>.boss…

⭐Unity 将电脑打开的窗口画面显示在程序中

1.效果&#xff1a; 下载资源包地址&#xff1a; Unity中获取桌面窗口 2.下载uWindowCapturev1.1.2.unitypackage 放入Unity工程 3.打开Single Window场景&#xff0c;将组件UwcWindowTexture的PartialWindowTitle进行修改&#xff0c;我以腾讯会议为例 感谢大家的观看&#xf…

QT开发 2024最新版本优雅的使用vscode开发QT

▬▬▬▬▬▶VS开发QT◀▬▬▬▬▬ &#x1f384;先看效果 &#x1f384;编辑环境变量 如图添加环境变量&#xff01;&#xff01;&#xff01; 东西全在QT的安装目录&#xff01;&#xff01;&#xff01; 找到的按照我的教程再装一次&#xff01;&#xff01;&#xff01; 点…

如何给AVR16芯片解锁

AVRM16核心板本身集成了强大的芯片自解锁功能模块&#xff0c;当由于熔丝位设置错误&#xff0c;导致芯片锁死&#xff0c;无法正常使用时候&#xff0c;可以利用畅学AVR16核心板上的解锁功能给芯片解锁。 &#xff08;如果芯片没有锁死&#xff0c;可以跳过此步骤&#xff09…

yolov5无人机视频检测与计数系统(创新点和代码)

标题&#xff1a;基于YOLOv5的无人机视频检测与计数系统 摘要&#xff1a; 无人机技术的快速发展和广泛应用给社会带来了巨大的便利&#xff0c;但也带来了一系列的安全隐患。为了实现对无人机的有效管理和监控&#xff0c;本文提出了一种基于YOLOv5的无人机视频检测与计数系…

排序之插入排序

在计算机科学中&#xff0c;排序算法是一种将一组元素按照某种特定顺序排列的方法。插入排序是一种简单且易于理解的排序算法&#xff0c;它的基本思想是将一个记录插入到已经排好序的有序表中&#xff0c;从而得到一个新的、记录数增1的有序表。 基本思想 插入排序的基本思想…

Ubuntu 20.04 Intel RealSense D435i 相机标定教程

下载编译code_utils mkdir -p ~/imu_catkin_ws/src cd ~/imu_catkin_ws/src catkin_init_workspace source ~/imu_catkin_ws/devel/setup.bash git clone https://github.com/gaowenliang/code_utils.git cd .. catkin_make报错&#xff1a;sumpixel_test.cpp:2:10: fatal err…

计算机网络 物理层

文章目录 物理层物理层的基本概念数据通信的基础知识数据通信系统的模型有关信道的几个基本概念信道的极限容量 物理层下面的传输媒体导引型传输媒体非引导型传输媒体 信道复用技术波分复用码的复用 宽带接入技术ADSL 技术光纤同轴混合网 (HFC 网&#xff09;FTTx 技术 物理层 …

基于sprinmgboot实习管理系统源码和论文

随着信息化时代的到来&#xff0c;管理系统都趋向于智能化、系统化&#xff0c;实习管理也不例外&#xff0c;但目前国内仍都使用人工管理&#xff0c;市场规模越来越大&#xff0c;同时信息量也越来越庞大&#xff0c;人工管理显然已无法应对时代的变化&#xff0c;而实习管理…

新生儿成长的阳光之钙:补充注意事项指南

引言&#xff1a; 钙是新生儿骨骼发育不可或缺的重要元素&#xff0c;对于宝宝的生长发育起着至关重要的作用。本文将深入探讨钙的功能、补充时机&#xff0c;以及在给新生儿补充钙时应该注意的事项&#xff0c;为小天使们提供最贴心的呵护。 第一部分&#xff1a;钙的重要性与…

【python入门】day21:向文件输出“奋斗成就更好的你”、输出北京的天气预报

向文件输出“奋斗成就更好的你” #向文件输出‘奋斗成就更好的你’ 第一种方式&#xff1a;使用print方式进行输出&#xff08;输出目的地是文件&#xff09; fpopen(e:/text.txt,w)#w只写模式&#xff0c;也可以用a读写模式 print(奋斗成就更好的你,filefp) fp.close() 第二种…

创建EasyCodeMybatisCodeHelperPro模板文件用于将数据库表生成前端json文件

在intellij idea中&#xff0c;通过插件EasyCodeMybatisCodeHelperPro&#xff0c;从现有的模板文件中选择一个复制粘贴&#xff0c;然后稍为修改&#xff0c;即可得到一个合适的模板文件。 现在的前端&#xff0c;越来越像后端。TypeScript替代了JavaScript&#xff0c;引入了…

压缩编码之变换的选择之离散余弦变换(DCT)和离散傅立叶变换(DFT)——数字图像处理

原理 变换的选择是一个关键的考量因素&#xff0c;它决定了数据是如何被压缩的。选择变换时考虑以下几个重要原则&#xff1a; 数据去关联性&#xff1a;变换的目的之一是减少数据中的相关性。例如&#xff0c;在图像压缩中&#xff0c;像素间往往高度相关。通过适当的变换&a…

统计学-R语言-1

文章目录 统计学介绍基本类型数据和变量数据抽样总结 统计学介绍 统计学(statistics)是“数据的科学” 1.是用以收集数据、分析数据和由数据得出结论的一组概念、原则和方法。 2.统计学进行推断的基础是数据(data)。数据不仅仅限于数字&#xff0c;也可能是图表、视频、音频或…

数据结构排序——详解快排及其优化和冒泡排序(c语言实现、附有图片与动图示意)

上次讲了选择排序和堆排序&#xff1a;数据结构排序——选择排序与堆排序 今天就来快排和冒泡 文章目录 1.快排1.1基本介绍1.2不同的分区方法及代码实现1.2.1Hoare版1.2.2挖坑版1.2.3 前后指针版 1.3快排的优化1.3.1三数取中选key1.3.2递归到小的子区间时&#xff0c;可以考虑…