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

news2024/11/24 15:30:42

一.应用的场景

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

二.最小生成树的定义

生成树:
图的生成树是它的一颗含有其所有顶点无环连通子图。
【简单说就是所有顶点连接在一起,并且没有环。
因此有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;
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Apache ActiveMQ RCE CNVD-2023-69477 CVE-2023-46604

漏洞简介 Apache ActiveMQ官方发布新版本&#xff0c;修复了一个远程代码执行漏洞&#xff0c;攻击者可构造恶意请求通过Apache ActiveMQ的61616端口发送恶意数据导致远程代码执行&#xff0c;从而完全控制Apache ActiveMQ服务器。 影响版本 Apache ActiveMQ 5.18.0 before 5.1…

ssh | OpenSSH - with TCP port forwarding | ssh通过 tcp转发数据 | ssh 隧道

讲的会有点啰嗦 一次抓包 发现的问题 tcpdump -vvv -X -n -i any -s0 host “xx.xx.xx.xx” and port 22 -w xxx.pcap 然后从数据中发现了一问题&#xff0c;总所周知&#xff0c;ssh 通过加密的方式传递数据 多以 也会把 ssh 当作隧道 通信 然后在抓的数据中发现了一些 tcp协议…

jmeter监控服务器资源使用情况

GitHub - undera/perfmon-agent: Server metrics fetching agent, based on SIGAR 下载安装包&#xff1a;ServerAgent-2.2.3.zip 解压先 启动&#xff0c;如果是windows运行startAgent.bat&#xff0c;如果是linux运行startAgent.sh 注意&#xff1a;linux上注意权限的问题…

CRM系统进行市场营销,这些功能可以派上用场。

现如今的企业想要做好营销&#xff0c;不仅仅依赖于一句玄之又玄的slogan亦或是电子邮件的狂轰乱炸。要想做好市场活动营销需要一个前提——那就是CRM管理系统发挥作用的地方。但CRM系统关于营销的功能太多了——对于不太了解的人来说很容易不知所措。那么&#xff0c;CRM系统做…

超声波清洗机哪个品牌值得推荐?值得入手超声波清洗机都在这

在繁忙的生活中&#xff0c;配戴眼镜朋友都清楚&#xff0c;眼镜常常因为各种污渍而失去原有的光泽&#xff0c;刚新配的眼镜是蹭蹭亮的&#xff0c;佩戴一段时间后就没有原先那么亮了&#xff0c;镜片上沾满了污渍、灰尘等&#xff0c;眼镜支架缝隙中也是一样&#xff0c;普通…

大话 JavaScript(Speaking JavaScript):第十六章到第二十章

第十六章&#xff1a;变量&#xff1a;作用域、环境和闭包 原文&#xff1a;16. Variables: Scopes, Environments, and Closures 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 本章首先解释了如何使用变量&#xff0c;然后详细介绍了它们的工作方式&#xff08;环境…

python爬虫实战(10)--获取本站热榜

1. 需要的类库 import requests import pandas as pd2. 分析 通过分析&#xff0c;本站的热榜数据可以直接通过接口拿到&#xff0c;故不需要解析标签&#xff0c;请求热榜数据接口 url "https://xxxt/xxxx/web/blog/hot-rank?page0&pageSize25&type" #本…

【集合大练习】---------------简易学生管理系统

目标&#xff1a; 实现学生对象新增&#xff0c;删除&#xff0c;查看&#xff0c;对象信息修改 整体实现思路&#xff1a; 1.定义学生类-------------创建学生对象 2.管理界面代码编写-------------命令提示面板 3.添加学生的代码编写---------add功能实现 4.查看学生信…

哪个品牌的运动耳机比较好?哪个运动耳机好?2024年运动耳机推荐

​对于追求健康生活方式的人&#xff0c;高质量的运动耳机是维持锻炼动力和专注的不可或缺的装备。在跑步、骑行或进行其他形式的锻炼时&#xff0c;运动耳机能为我们提供动感的音乐&#xff0c;为运动体验增添活力。以下是市场上一些表现出色的运动耳机&#xff0c;都来看看有…

红黑树的了解以及代码实现

什么是红黑树 红黑树是在二叉搜索树的基础上添加颜色&#xff0c;通过对任何一条路径的颜色的限制&#xff0c;确保红黑树的任何一条路径不会超过其他路径的两倍&#xff0c;是一棵近似平衡的树。 红黑树的节点不是红色就是黑色&#xff0c;其节点的排列除了需要按二插搜索树的…

微信,支付宝“免密支付”,关闭教程!

不久前&#xff0c;一位中年妇女捡到了一部手机&#xff0c;并使用免密支付的方式消费掉了手机里的所有余额。这一事件在微博上成为了热搜话题&#xff0c;引起了网友们的热议。 据报道&#xff0c;一名泸州市的居民在捡到一部他人的手机后&#xff0c;发现该手机没有设置锁屏密…

全网最详细mysql5.7安装(保姆级别)

文章目录 数据库MySQL5.7安装包安装环境变量配置检测是否安装配置成功MySQL 启动和关闭 数据库 概念&#xff1a;数据库&#xff08;DataBase&#xff09;简称&#xff1a;DB 用于存储和管理数据的仓库 数据库的特点 1、持久化存储数据&#xff0c;其实数据库就是一个文件系统…

【MATLAB】 TVFEMD信号分解算法

有意向获取代码&#xff0c;请转文末观看代码获取方式~ 1 基本定义 TVFEMD (Time-Variant Filtered Empirical Mode Decomposition) 是一种信号分解算法&#xff0c;它是基于 EMD (Empirical Mode Decomposition) 方法发展而来的。 EMD是一种自适应的数据分析方法&#xff0…

微电网能效管理系统在寿宁县五校迁建项目的设计与应用——安科瑞赵嘉敏

基本信息&#xff1a; 项目名称&#xff1a;寿宁县五校迁建项目(现为寿宁县一中)企业微电网能效管理系统 项目地点&#xff1a;福建省寿宁县 实施时间&#xff1a;2023年4月 项目总览图&#xff1a; 项目简介&#xff1a; 寿宁县第一中学创办于1938年7月&#xff0c;是一所…

目标跟踪算法的目标丢失与遮挡处理 - 注意力机制

目标跟踪算法在处理目标遮挡和丢失情况时&#xff0c;采用了多种技术和策略。这些技术主要集中在提高算法的鲁棒性和适应性上&#xff0c;使其能够在复杂环境中有效跟踪目标。以下是一些常见的处理方法&#xff1a; 多模型融合&#xff1a;通过结合多个跟踪模型或特征表示&…

Container ansible disguises local ansible 【容器 ansible 伪装本地 ansible】

预备条件&#xff1a; ctr & crictl $ nerdctl & containerd install了解 kubespray 是什么 kubespray 包含 ansible、ansible-playbook命令以及通过kubespray项目安装kubernetes集群的介质。 nerdctl pull quay.io/kubespray/kubespray:v2.23.1 nerdctl save -o qu…

中间捕获事件:IntermediateCatchingEvent(TimerEvent)

一&#xff1a;TimerEvent https://monday.blog.csdn.net/article/details/134435415 应用场景&#xff1a; 定时启动流程&#xff1a;该类型节点作为流程的开始节点&#xff0c;不需要显式启动流程&#xff0c;只需要部署。节点延时审批。节点超时处理&#xff1a;对在指定…

Linux习题3

解析&#xff1a; grep&#xff1a;查找文件内的内容 gzip&#xff1a;压缩文件&#xff0c;文件经压缩后会增加 gz&#xff1a;扩展名 find&#xff1a;在指定目录下查找文件 解析&#xff1a; A hosts文件是Linux系统上一个负责ip地址与域名快速解析的文件&#xff0c;以…

linux搭建SRS服务器

linux搭建SRS服务器 文章目录 linux搭建SRS服务器SRS说明实验说明搭建步骤推流步骤查看web端服务器拉流步骤final SRS说明 SRS&#xff08;simple Rtmp Server&#xff09;,是一个简单高效的实时视频服务器&#xff0c;支持RTMP/WebRTC/HLS/HTTP-FLV/SRT, 是国人自己开发的一款…

Object.keys()

目录 1、Object.keys() 是什么&#xff1f; 2、Object.keys(obj) 用法&#xff1a; 2.1 如果对象是一个对象&#xff0c;会返回对象的属性名组成的数组&#xff1b; 2.2 如果对象是一个数组&#xff0c;则返回索引组成的数组&#xff1a; 2.3 如果是字符串&#xff0c;返回…