最小生成树刷题笔记

2024-05-13 00:44
文章标签 笔记 最小 生成 树刷题

本文主要是介绍最小生成树刷题笔记,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

算法基础:

最小生成树是所有节点的最小连通子图!!!!

首先是prim算法三部曲:

(1)找到距离最小生成树最近的节点。

(2)将距离最小生成树最近的节点加入到最小生成树中。

(3)更新非最小生成树节点到最小生成树的距离。

实现步骤:

首先我们利用一个for循环遍历n - 1遍,因为我们从第1个节点开始将其加入到生成树之中后知道添加到还剩两个节点时,我们可以发现当我们添加玩倒数第二个节点后,最后一个节点的mindist数值在处理倒数第二个节点的第三部更新过程中已经得到了,这个距离不是倒数第二个节点到它的距离grid[cur][j]就是之前已经得到的它与某个节点之间的距离mindist[j]。

(1)寻找最近节点:

判断最近节点的三个条件:1.未在生成树中。  2.距离生成树距离最短     3.选取最短距离我们先随便选出一个节点然后再与其他节点比较

if(!isvisited[j] && (cur = -1 || mindist[cur] > mindist[j])              Cur = j;

这里:Mindist[cur] < mindist[j]包含了两层含义:首先我们要明确我们要找离生成树距离最短的点,mindist数组中存的只就是节点到生成树的最小距离,如果后续的节点的mindist的值要小于前面得出的mindist值,那么就将当前节点的标记j赋值给cur。

这里我们每遍历一层就会将cur置为-1以便我们可以最快选取一个随机节点并遍历后面的节点与之比较。而第二层的mindist[j]的值已经在第一层的第三步更新操作中得到。

(2)将最近节点加入生成树:

isintree[cur] = true;

(3)更新非生成树节点到生成树距离:

利用一个for循环遍历所以非生成树节点,并更新起距离mindist[j] < grid[cur][j] ? Mindist[j] = mindist[j] : mindist[j] = grid[cur][j]

这列的更新操作有两层意思:第一是遍历的外部节点需要与生成树有连接,也就是grid[cur][j] < mindist[j] == INT_MAX,第二是当前节点已经跟生成树有连接但还没选入进入生成树(预备党员哈哈)因为之前节点的更新扩散操作使得与之前节点有连接的j节点有了mindist的数值,所以我们拿grid[cur][j]与之前得到的最近距离mindist作比较保留更小的那个值赋值给mindist[j]

经过上面的分析,我认为prim算法的关键一定是要明确mindist数组的含义:是当前节点到最小生成树的最小距离。因为我们的第一步选点用到mindist数组来根据各个点到生成树(第一步时就是到源点的距离)的最小距离来选取最近节点,我们的第三步更新也是由于新加入的点导致未加入节点到生成树的距离改变,通过grid[cur][j] 与mindist[j]来判断是否需要更改mindist的值。

#include<iostream>
#include<vector>
using namespace std;
int main() {
    int v, e;
    int x, y, k;
    cin >> v >> e;
    // 填一个默认最大值,题目描述val最大为10000
    vector<vector<int>> grid(v + 1, vector<int>(v + 1, 10001));
    while (e--) {
        cin >> x >> y >> k;
        // 因为是双向图,所以两个方向都要填上
        grid[x][y] = k;
        grid[y][x] = k;

    }
    // 所有节点到最小生成树的最小距离
    vector<int> minDist(v + 1, 10001);

    // 这个节点是否在树里
    vector<bool> isInTree(v + 1, false);

    // 我们只需要循环 n-1次,建立 n - 1条边,就可以把n个节点的图连在一起
    for (int i = 1; i < v; i++) {

        // 1、prim三部曲,第一步:选距离生成树最近节点
        int cur = -1; // 选中哪个节点 加入最小生成树
        for (int j = 1; j <= v; j++) { // 1 - v,顶点编号,这里下标从1开始
            //  选取最小生成树节点的条件:
            //  (1)不在最小生成树里
            //  (2)距离最小生成树最近的节点
            //  (3)只要不在最小生成树里,先默认选一个节点 ,在比较 哪一个是最小的
            //  理解条件3 很重要,才能理解这段代码:(cur == -1 || minDist[j] < minDist[cur])
            if (!isInTree[j] && (cur == -1 || minDist[j] < minDist[cur])) {
                cur = j;
            }
        }
        // 2、prim三部曲,第二步:最近节点(cur)加入生成树
        isInTree[cur] = true;

        // 3、prim三部曲,第三步:更新非生成树节点到生成树的距离(即更新minDist数组)
        // cur节点加入之后, 最小生成树加入了新的节点,那么所有节点到 最小生成树的距离(即minDist数组)需要更新一下
        // 由于cur节点是新加入到最小生成树,那么只需要关心与 cur 相连的 非生成树节点 的距离 是否比 原来 非生成树节点到生成树节点的距离更小了呢
        for (int j = 1; j <= v; j++) {
            // 更新的条件:
            // (1)节点是 非生成树里的节点
            // (2)与cur相连的某节点的权值 比 该某节点距离最小生成树的距离小
            // 很多录友看到自己 就想不明白什么意思,其实就是 cur 是新加入 最小生成树的节点,那么 所有非生成树的节点距离生成树节点的最近距离 由于 cur的新加入,需要更新一下数据了
            if (!isInTree[j] && grid[cur][j] < minDist[j]) {
                minDist[j] = grid[cur][j];
            }
        }
    }
    // 统计结果
    int result = 0;
    for (int i = 2; i <= v; i++) { // 不计第一个顶点,因为统计的是边的权值,v个节点有 v-1条边
        result += minDist[i];
    }
    cout << result << endl;

}

leetcode - 1584:连接所有点的最小费用

由于这道题给出的是点集,我们可以想到使用prim来处理点集的最小生成树问题,这道题不好使用kruskal来解决因为还要求边那就需要我们去求各个点的组合会复杂很多。

就是利用题目中的公式建立邻接矩阵在套用上面的模板即可:

class Solution {
public:
    int minCostConnectPoints(vector<vector<int>>& points) {
        int n = points.size();
        vector<vector<int>> grid(n, vector<int>(n, 0));
        // 计算任意两点之间的曼哈顿距离并填充到grid矩阵中
        for(int i = 0; i < n; i++){
            for(int j = i + 1; j < n; j++){
                int x = abs(points[i][0] - points[j][0]);
                int y = abs(points[i][1] - points[j][1]);
                grid[i][j] = grid[j][i] = x + y;
            }
        }
        vector<bool> isvisited(n, false);
        vector<int> mindist(n, INT_MAX);
        mindist[0] = 0; // 从第一个点开始
        int res = 0;
        for(int i = 0; i < n - 1; i++){
            int cur = -1;
            // 选择当前距离生成树最近的节点
            for(int j = 0; j < n; j++){
                if(!isvisited[j] && (cur == -1 || mindist[j] < mindist[cur])){
                    cur = j;
                }
            }
            isvisited[cur] = true;
            // 更新其他节点到生成树的距离
            for(int j = 0; j < n; j++){
                if(!isvisited[j] && mindist[j] > grid[cur][j]){
                    mindist[j] = grid[cur][j];
                }
            }
        }
        for(int i = 1; i < n; i++){
            res += mindist[i];
        }
        return res;
    }

这篇关于最小生成树刷题笔记的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/984209

相关文章

Python实现自动化Word文档样式复制与内容生成

《Python实现自动化Word文档样式复制与内容生成》在办公自动化领域,高效处理Word文档的样式和内容复制是一个常见需求,本文将展示如何利用Python的python-docx库实现... 目录一、为什么需要自动化 Word 文档处理二、核心功能实现:样式与表格的深度复制1. 表格复制(含样式与内容)2

python如何生成指定文件大小

《python如何生成指定文件大小》:本文主要介绍python如何生成指定文件大小的实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录python生成指定文件大小方法一(速度最快)方法二(中等速度)方法三(生成可读文本文件–较慢)方法四(使用内存映射高效生成

Maven项目中集成数据库文档生成工具的操作步骤

《Maven项目中集成数据库文档生成工具的操作步骤》在Maven项目中,可以通过集成数据库文档生成工具来自动生成数据库文档,本文为大家整理了使用screw-maven-plugin(推荐)的完... 目录1. 添加插件配置到 pom.XML2. 配置数据库信息3. 执行生成命令4. 高级配置选项5. 注意事

MybatisX快速生成增删改查的方法示例

《MybatisX快速生成增删改查的方法示例》MybatisX是基于IDEA的MyBatis/MyBatis-Plus开发插件,本文主要介绍了MybatisX快速生成增删改查的方法示例,文中通过示例代... 目录1 安装2 基本功能2.1 XML跳转2.2 代码生成2.2.1 生成.xml中的sql语句头2

使用Python自动化生成PPT并结合LLM生成内容的代码解析

《使用Python自动化生成PPT并结合LLM生成内容的代码解析》PowerPoint是常用的文档工具,但手动设计和排版耗时耗力,本文将展示如何通过Python自动化提取PPT样式并生成新PPT,同时... 目录核心代码解析1. 提取 PPT 样式到 jsON关键步骤:代码片段:2. 应用 JSON 样式到

SpringBoot实现二维码生成的详细步骤与完整代码

《SpringBoot实现二维码生成的详细步骤与完整代码》如今,二维码的应用场景非常广泛,从支付到信息分享,二维码都扮演着重要角色,SpringBoot是一个非常流行的Java基于Spring框架的微... 目录一、环境搭建二、创建 Spring Boot 项目三、引入二维码生成依赖四、编写二维码生成代码五

Android与iOS设备MAC地址生成原理及Java实现详解

《Android与iOS设备MAC地址生成原理及Java实现详解》在无线网络通信中,MAC(MediaAccessControl)地址是设备的唯一网络标识符,本文主要介绍了Android与iOS设备M... 目录引言1. MAC地址基础1.1 MAC地址的组成1.2 MAC地址的分类2. android与I

PyQt5+Python-docx实现一键生成测试报告

《PyQt5+Python-docx实现一键生成测试报告》作为一名测试工程师,你是否经历过手动填写测试报告的痛苦,本文将用Python的PyQt5和python-docx库,打造一款测试报告一键生成工... 目录引言工具功能亮点工具设计思路1. 界面设计:PyQt5实现数据输入2. 文档生成:python-

IDEA自动生成注释模板的配置教程

《IDEA自动生成注释模板的配置教程》本文介绍了如何在IntelliJIDEA中配置类和方法的注释模板,包括自动生成项目名称、包名、日期和时间等内容,以及如何定制参数和返回值的注释格式,需要的朋友可以... 目录项目场景配置方法类注释模板定义类开头的注释步骤类注释效果方法注释模板定义方法开头的注释步骤方法注

Python如何自动生成环境依赖包requirements

《Python如何自动生成环境依赖包requirements》:本文主要介绍Python如何自动生成环境依赖包requirements问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑... 目录生成当前 python 环境 安装的所有依赖包1、命令2、常见问题只生成当前 项目 的所有依赖包1、