最小生成树问题(Prim算法和Kruskal算法)

news2024/11/23 0:52:57

问题引入:

        这算是一道模板题了,只不过这次在做的时候感觉又学到了些新的东西,之前都是数据结构里学的,因为用惯了C++,所以就想摆脱那些邻接数组之类的写法,用STL试一下,在其中把我遇到的一些问题写出来分享给大家:

关于最小生成树:

       一个有 n 个结点的连通图的生成树是原图的极小连通子图,且包含原图中的所有 n 个结点,并且有保持图连通的最少的边。 [1]  最小生成树可以用kruskal(克鲁斯卡尔)算法或prim(普里姆)算法求出。

        其次是关于最小生成树的唯一性问题一直困扰了我很长时间,网上看到些答案都说是不唯一的,但是它的权值却是唯一的,举个例子,等边三角形的三个顶点,不管连接哪两个点都是最小生成树,所以在Prim算法中,我们可以任意取一条边的一个顶点作为第一条进入最小生成树的一条边,也可以将各个边按边权排序后让最小的边进入,在上学期的数据结构中,我一直是默认让第一条边直接进入最小生成树,这里可能有人问,万一你选的那一条边恰好不在最小生成树的边集中呢?起初我也是这么想的,但是prim算法每次都是把当前最小的边加入最小生成树,所以一个点要想进入最小生成树,就需要和其他的点连通,怎样保证连通且最小的呢,当然是选择最小的边,选择任意的一个顶点开始之所以成立,就是因为最小生成树不仅仅可以从叶节点开始找,也可以从根节点开始找,只不过要保证在寻找过程中不能连通(一般采用visited数组来标记已访问顶点)。

1.Prim算法(筛选节点)

      思路:先将各个边按权值由小到大排序,先选择边权最小的边,设一个集合来判断节点,当节点数等于n时就可以找到最小的生成树

class Solution {
public:
   
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 返回最小的花费代价使得这n户人家连接起来
     * @param n int n户人家的村庄
     * @param m int m条路
     * @param cost intvector<vector<>> 一维3个参数,表示连接1个村庄到另外1个村庄的花费的代价
     * @return int
     */
    static bool cmp(vector<int>& x, vector<int>& y){ //重载比较,按照边权递增
        return x[2] < y[2];
    }
    
    int miniSpanningTree(int n, int m, vector<vector<int> >& cost) {
        // write code here
       unordered_set<int> points;//集合可以避免重复
       int ans=0;//权值结果
       sort(cost.begin(),cost.end(),cmp);
       ans+=cost[0][2];//排序后第一条便即为最小边
       points.insert(cost[0][0]);
       points.insert(cost[0][1]);
       //点入集合
       while(points.size()<n)
       {
        for(auto iter=cost.begin();iter!=cost.end();iter++)
        {
            //寻找与当前集合内的点相连的未选择的边
            if((points.find((*iter)[0]) != points.end() && points.find((*iter)[1]) == points.end()) || (points.find((*iter)[1]) != points.end() && points.find((*iter)[0]) == points.end()))
            {
                ans+=(*iter)[2];
                points.insert((*iter)[0]);
                points.insert((*iter)[1]);
                cost.erase(iter);
                break;
            }
        }
       }
       return ans;

    }
};

2.kruskal算法

前言:并查集

      并查集,在一些有N个元素的集合应用问题中,我们通常是在开始时让每个元素构成一个单元素的集合,然后按一定顺序将属于同一组的元素所在的集合合并,其间要反复查找一个元素在哪个集合中。这就类似于族谱,如果想调查你和一个人是否有亲戚,那就从你和那个人开始往上调查族谱,找到了两个人的祖先有关系,那就是亲戚。

       思路:初始时将所有顶点的边全都看作没有在集合内,定义声明寻找顶点父亲节点的函数,在选择边时,如果这条边的两个顶点的父节点相等,那么表示加入该边后会构成回路,所以判断出该边不可取

class Solution {
public:
   
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 返回最小的花费代价使得这n户人家连接起来
     * @param n int n户人家的村庄
     * @param m int m条路
     * @param cost intvector<vector<>> 一维3个参数,表示连接1个村庄到另外1个村庄的花费的代价
     * @return int
     */
    static bool cmp(vector<int>& x, vector<int>& y){ //重载比较,按照边权递增
        return x[2] < y[2];
    }
    int find(vector<int>&parent,int x)
    {
        if(parent[x]!=x)//该点还没有被选择
         parent[x]=find(parent,parent[x]);//parent[x]中保存的是x节点的父亲,但是不是祖先
         return parent[x];
    }
    int miniSpanningTree(int n, int m, vector<vector<int> >& cost) {
        // write code here
       vector<int> parent(n+1);
       for(int i=0;i<=n;i++)
        parent[i]=i;//初始时将自己的祖先节点设置为自己
       sort(cost.begin(),cost.end(),cmp);
       int ans=0;
       for(auto iter=cost.begin();iter!=cost.end();iter++)
       {
         int x=(*iter)[0];
         int y=(*iter)[1];
         int px=find(parent,x);
         int py=find(parent,y);
         if(px!=py)//表示当前的边加入不会构成回路,可以加入最小生成树
         {
               ans+=(*iter)[2];
               parent[px]=py;//更新其父亲节点表示在同一个集合
         }
       }
       return ans;
    }
};

以上便是我对最小生成树算法的进一步理解,以上见解如有错误请不吝赐教,希望可以共同进步,谢谢大家。

最好的药物是忙碌,最好的治愈是读书;

最好的爱情是自爱,最好的自爱是自律。

不要在二十出头的年纪就整天为了那点感情emo,等你成功的那天,双向奔赴的那个人就一定会出现的。

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

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

相关文章

【论文翻译】边缘应用中加速卷积神经网络的剪枝算法综述

摘要 随着卷积神经网络&#xff08;CNN&#xff09;模型大小的增加&#xff0c;模型压缩和加速技术对于在边缘设备上部署这些模型变得至关重要。在本文中&#xff0c;我们对修剪进行了全面的调查&#xff0c;这是一种主要的压缩策略&#xff0c;可以从CNN模型中删除非关键或冗…

iOS_Memory Leak 内存泄露治理

1、内存分类 官方文档介绍 app 的内存分三类&#xff1a; Leaked memory&#xff1a;Memory unreferenced by your application that cannot be used again or freed (also detectable by using the Leaks instrument) Abandoned memory&#xff1a;Memory still referenced b…

设计模式 - 结构型模式_桥接模式

文章目录结构型模式概述CaseBad ImplBetter Impl小结结构型模式 结构型模式主要是解决如何将对象和类组装成较大的结构&#xff0c; 并同时保持结构的灵活和⾼效。 结构型模式包括&#xff1a;适配器、桥接、组合、装饰器、外观、享元、代理&#xff0c;这7类 概述 桥接模式的…

2023牛客寒假算法基础集训营4

A-清楚姐姐学信息论 链接&#xff1a;登录—专业IT笔试面试备考平台_牛客网 来源&#xff1a;牛客网 不同进制对于信息的表示效率不同&#xff0c;清楚姐姐最近学习了信息论中使用不同进制表示信息的方法&#xff0c;她现在想要比较两种不同进制表示信息时&#xff0c;谁的…

从软件角度看PCIe设备的硬件结构

从软件角度看PCIe设备的硬件结构 文章目录从软件角度看PCIe设备的硬件结构参考资料&#xff1a;一、 PCIe接口引脚二、 从软件角度理解硬件接口2.1 PCI/PCIe地址空间转换2.2 PCIe上怎么传输地址、数据三、 PCIe系统的硬件框图致谢参考资料&#xff1a; 《PCI Express Technolo…

ElasticSearch概念与架构原理

文章目录一、概述二、ElasticSearch架构原理三、ElasticSearch搜索入门一、概述 ElasticSearch简介 简介 ES是建立在Lucene基础之上的分布式准实时搜索引擎&#xff0c;它所提供的诸多功能中有一大优点&#xff0c;就是实时性好。比如&#xff1a;在业务需求中&#xff0c;新增…

计算机图形学 第7章 自由曲线曲面

先说好&#xff0c;第八章不学。 目录学习目标曲线与曲面的表示形式插值与逼近Bezier曲线定义一次Bezier曲线二次Bezier曲线⭐⭐⭐三次Bezier曲线⭐⭐⭐三次Bezier曲线的Bernstein基函数&#xff1a;Bernstein基函数的性质Bezier曲线的性质de Casteljau算法几何作图法绘制Bezie…

Struts2之拦截器

Struts2之拦截器1、Struts2体系架构1.1、执行流程1.2、核心接口和类1.3、流程简图2、Struts2拦截器2.1、使用拦截器的目的2.2、拦截器的简介2.3、拦截器的工作原理2.4、拦截器的使用2.4.1、创建自定义拦截器2.4.2、struts.xml中定义和配置拦截器2.4.3、Struts2默认拦截器2.4.4、…

Leetcode.2319 判断矩阵是否是一个 X 矩阵

题目链接 Leetcode.2319 判断矩阵是否是一个 X 矩阵 Rating : 1201 题目描述 如果一个正方形矩阵满足下述 全部 条件&#xff0c;则称之为一个 X矩阵 &#xff1a; 矩阵对角线上的所有元素都 不是 0 矩阵中所有其他元素都是 0 给你一个大小为 n x n的二维整数数组 grid&#…

ElasticSearch - 旅游酒店案例es功能实现

目录 案例 搜索与分页功能 条件过滤功能 附近的酒店功能 广告置顶功能 HotelService(es操作)总览 案例 搜索与分页功能 案例需求&#xff1a;实现旅游的酒店搜索功能&#xff0c;完成关键字搜索和分页实现步骤如下&#xff1a;1.定义实体类&#xff0c;接收前端请求实体…

微信小程序用vant自定义tabbar页面并跳转相应页面

0.前置安装 步骤一 安装 vant 组件库 npm i vant/weapp -S --production下载完后要npm构建才能使用 步骤二 修改 app.json 将 app.json 中的 "style": "v2" 去除&#xff0c;小程序的新版基础组件强行加上了许多样式&#xff0c;难以覆盖&#xff0c;不…

分布式定时任务框架选型

目录 1. 前言 2. 定时任务框架 3. 分布式任务调度系统对比 4. 和quartz框架对比 5. 综合对比 6. 总结和结论 7. 附定时任务的其他方案 1. 前言 我们先思考下面几个业务场景的解决方案: 支付系统每天凌晨1点跑批&#xff0c;进行一天清算&#xff0c;每月1号进行上个月清…

【算法】快速排序算法原理及实现

1.什么是快速排序算法 快速排序是对冒泡排序的一种改良版&#xff0c;通过一趟排序&#xff0c;把要排序的序列分割成两个部分&#xff0c;一部分的所有数据要比另一部分的数据都小&#xff0c;然后再根据这两部分的数据来进行快速排序。以此来达到整一个数据都变成了有序序列…

AI算法创新赛-人车目标检测竞赛总结01

AI0000020摘要:人车目标检测竞赛主要考察目标检测算法与 TPU 部署推理&#xff0c;主要考察算法选型与调 优&#xff0c;面向算能 TPU 迁移部署与推理加速两项能力;主要考核目标是算法效果(mAP)与推 理性能(单张图片推理时间)。针对这些要求&#xff0c;笔者从算法选型&#xf…

【实际开发11】- 统计 / 科学计算 - 1

目录 1. sql 统计返回值为 null 时 , 赋值 为 : 0 ( return UI ) 1. 手动 null 判断 , 进行 “0” 赋值 2. XxxxVO 展示对象 , 初始化时 , 赋值默认值 ( 待优化 ) 2. 统计异常 1. 注意中间表数据的维护 ( 同步删除 / 避免手动删数据 ) 3. 精度损失 1. Java 类型 float、…

.NET(C#、VB)APP开发——Smobiler平台控件介绍:LiveStream和LiveStreamPlayer

本文简述如何在Smobiler中使用LiveStream和LiveStreamPlayer。 LiveStream 直播推送插件 Step 1. 新建一个SmobilerForm窗体&#xff0c;并在窗体中加入LiveStream和Button&#xff0c;布局如下 选中LisvStream&#xff0c;在设计器中设置Url&#xff08;需要事先准备一个视频…

【面试原型链】前端面试那些事(1)之原型链详解

【写在前面】辞旧迎新的春季佳节&#xff0c;在这里博主先祝各位看官新的一年赚钱多多&#xff0c;知识满满&#xff0c;年后谈到面试&#xff0c; 好多人在面试的时候就倒在原型链知识点上面&#xff0c;主要原因还是基本功不够扎实&#xff0c;针对以前的知识我也计划在2023年…

C语言小题,通过指向结构体变量的指针变量输出结构体变量中成员的信息。(指针结构体变量的指针)

前言&#xff1a; 此篇是针对 指针结构体变量的指针 方面的练习。 解题思路&#xff1a; 在已有的基础上&#xff0c;本题要解决两个问题&#xff1a; &#xff08;1&#xff09;怎样对结构体变量成员赋值&#xff1b; &#xff08;2&#xff09;怎样通过指向结构体变量的指针…

天云数据:Hubble数据库系统自主研发率99.62%,是真正的信创数据库

软件是新一代信息技术的灵魂&#xff0c;是数字经济发展的基础&#xff0c;是制造强国、网络强国、数字中国建设的关键支撑。2021年&#xff0c;工信部印发的《“十四五”软件和信息技术服务业发展规划》明确指出&#xff0c;要聚力攻坚基础软件&#xff0c;关键基础软件补短板…

Javascript基础复盘5

内置对象 值属性 这些全局属性返回一个简单值&#xff0c;这些值没有自己的属性和方法。 InfinityNaNundefinedglobalThis函数属性 全局函数可以直接调用&#xff0c;不需要在调用时指定所属对象&#xff0c;执行结束后会将结果直接返回给调用者。 eval()uneval()isFinite()isN…