AcWing859. Kruskal算法求最小生成树

news2024/9/30 19:30:06

一定要看这个链接的讲解视频:强烈推荐!!!【图-最小生成树-Prim(普里姆)算法和Kruskal(克鲁斯卡尔)算法】

文章目录

  • 1.题目
  • 2.Kruskal基本思想:
  • 3.逐行解释代码:

1.题目

在这里插入图片描述

2.Kruskal基本思想:

Kruskal算法是一种用于求解加权连通图的最小生成树问题的贪心算法。它的基本思想可以概括为以下几个步骤:

  1. 边排序:将图中的所有边按照权重从小到大进行排序。

  2. 初始化并查集:创建一个并查集来跟踪图中的各个连通分量。开始时,每个顶点都是一个独立的连通分量,即每个顶点的父节点指向自己。

  3. 选择边:从排序后的边列表中选择边,每次选择时,都选择当前最小的边。为了确保添加的边不会形成环,使用并查集来检查当前选择的边的两个顶点是否属于同一个连通分量。

  4. 检查连通分量:在添加边之前,使用并查集的 find 操作来确定边的两个顶点是否已经在同一个连通分量中。如果两个顶点已经在同一个连通分量中,则跳过这条边;如果不在同一个连通分量中,则将它们合并到同一个连通分量中。

  5. 构建最小生成树:重复步骤3和步骤4,直到添加了 ( n-1 ) 条边(其中 ( n ) 是图中顶点的数量),这时就构成了一棵包含所有顶点的最小生成树。

  6. 结束条件:如果在选择边的过程中,发现剩余的边不足以连接所有顶点(即连通分量的数量大于1),则说明图不连通,无法构建最小生成树。

Kruskal算法的效率主要依赖于边排序和并查集的操作。边排序通常使用归并排序或其他高效的排序算法来完成,而并查集提供了快速的连通分量检查和合并操作。算法的时间复杂度主要取决于排序和并查集操作的时间复杂度,通常为 O ( E log ⁡ E ) O(E \log E) O(ElogE),其中 E E E是边的数量。

#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

const int N = 100010, M = 200010, INF = 0x3f3f3f3f;

int n, m;
int p[N];

struct Edge
{
    int a, b, w;
	//对边权排序的时候会进行Edge的比较,因此需要重载operator<
    bool operator< (const Edge &W)const
    {
        return w < W.w;
    }
}edges[M];

int find(int x)
{
    if (p[x] != x) p[x] = find(p[x]);
    return p[x];
}

int kruskal()
{
    sort(edges, edges + m);

    for (int i = 1; i <= n; i ++ ) p[i] = i;    // 初始化并查集

    int res = 0, cnt = 0;
    for (int i = 0; i < m; i ++ )
    {
        int a = edges[i].a, b = edges[i].b, w = edges[i].w;

        a = find(a), b = find(b);
        if (a != b)//不在一个连通分量里面,没有成环,可以在ab点之间添加进去一条边,
        {
            p[a] = b;
            res += w;
            cnt ++ ;
        }
    }
	//n个点,最小生成树里面应该包含n-1条边,如果cnt小于n-1说明有的不连通,只能放弃
    if (cnt < n - 1) return INF;
    return res;
}

int main()
{
    scanf("%d%d", &n, &m);

    for (int i = 0; i < m; i ++ )
    {
        int a, b, w;
        scanf("%d%d%d", &a, &b, &w);
        edges[i] = {a, b, w};
    }

    int t = kruskal();

    if (t == INF) puts("impossible");
    else printf("%d\n", t);

    return 0;
}


3.逐行解释代码:

当然,下面是对代码中每一行的详细解释:

#include <cstring>

包含 C 标准库中的字符串处理函数。

#include <iostream>

包含 C++ 标准库中的输入输出流相关函数。

#include <algorithm>

包含 C++ 标准库中的算法相关函数,比如排序函数 sort

using namespace std;

使用标准命名空间,这样在使用标准库中的函数和对象时就不需要加 std:: 前缀。

const int N = 100010, M = 200010, INF = 0x3f3f3f3f;

定义常量 N 为顶点的最大数量,M 为边的最大数量,INF 为一个很大的数,表示无法连接的状态。

int n, m;

定义变量 n 存储顶点数量,m 存储边的数量。

int p[N];

定义数组 p 用于存储并查集的父节点信息。

struct Edge
{
    int a, b, w;

定义结构体 Edge 用于存储边的信息,包括两个顶点 ab,以及边的权重 w

    bool operator< (const Edge &W)const
    {
        return w < W.w;
    }

重载小于运算符,用于比较两条边的权重,以便后续排序。

}edges[M];

定义数组 edges 存储所有的边。

int find(int x)
{
    if (p[x] != x) p[x] = find(p[x]);
    return p[x];
}

定义 find 函数,用于并查集的查找操作,如果 x 不是其自己的父节点,则递归查找其父节点,并进行路径压缩。

int kruskal()
{
    sort(edges, edges + m);

定义 kruskal 函数,并在函数内部对所有边按照权重进行排序。

    for (int i = 1; i <= n; i ++ ) p[i] = i;

初始化并查集,每个顶点的父节点都是自己。

    int res = 0, cnt = 0;

定义变量 res 用于存储最小生成树的总权重,cnt 用于存储已经加入最小生成树的边的数量。

    for (int i = 0; i < m; i ++ )
    {
        int a = edges[i].a, b = edges[i].b, w = edges[i].w;

遍历所有边,提取每条边的两个顶点和权重。

        a = find(a), b = find(b);

对每条边的两个顶点进行查找,获取它们的根节点。

        if (a != b)
        {
            p[a] = b;
            res += w;
            cnt ++ ;
        }
    }

如果两个顶点的根节点不同,说明它们不属于同一个集合,可以将它们合并,更新并查集,累加权重到 res,并增加 cnt

    if (cnt < n - 1) return INF;
    return res;
}

如果加入最小生成树的边的数量小于顶点数量减一,说明无法构成最小生成树,返回 INF;否则返回最小生成树的总权重。

int main()
{
    scanf("%d%d", &n, &m);

main 函数中,使用 scanf 函数读取顶点和边的数量。

    for (int i = 0; i < m; i ++ )
    {
        int a, b, w;
        scanf("%d%d%d", &a, &b, &w);
        edges[i] = {a, b, w};
    }

读取每条边的信息,包括两个顶点和边的权重,并将它们存储到 edges 数组中。

    int t = kruskal();

调用 kruskal 函数计算最小生成树的权重。

    if (t == INF) puts("impossible");
    else printf("%d\n", t);

根据 kruskal 函数的返回值判断是否能够构成最小生成树,如果不能则输出 “impossible”,否则输出最小生成树的总权重。

    return 0;
}

程序正常结束,返回 0。

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

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

相关文章

sql-labs46-50通关攻略

第46关 一.查询数据库 http://172.16.1.142/Less-46/?sort1%20and%20updatexml(1,concat(0x7e,(select%20database()),0x7e),1)--http://172.16.1.142/Less-46/?sort1%20and%20updatexml(1,concat(0x7e,(select%20database()),0x7e),1)-- 二.查表 http://172.16.1.142/Les…

Eureka:Spring Cloud中的服务注册与发现如何实现?

Eureka&#xff1a;Spring Cloud中的服务注册与发现如何实现&#xff1f; 1、什么是服务注册与发现&#xff1f;2、Eureka的工作原理3、Eureka的优势 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; 在微服务架构的浪潮中&#xff0c;服务注…

谷歌的 GameNGen:无需游戏引擎,人工智能模拟 “毁灭战士“,开辟新天地

谷歌公司的研究人员创建了一个神经网络&#xff0c;可以在不使用传统游戏引擎的情况下生成经典射击游戏《毁灭战士》的实时游戏&#xff0c;从而实现了人工智能领域的一个重要里程碑。这个名为 GameNGen 的系统标志着人工智能向前迈出了重要一步&#xff0c;它能在单芯片上以每…

ffmpeg教程及加速视频转码

ffmpeg教程及加速视频转码 1、ffmpeg简介&#xff1a; ffmpeg来自MPEG视频编码标准。 是一套可以用来记录&#xff0c;转换数字音频、视频&#xff0c;并能将其转化为流的开源计算机程序。 可以轻易的实现多种视频格式之间的相互转换。 2、基础知识&#xff1a; 容器、文件…

2d像素游戏基本架构

目录 2D像素游戏的基本架构通常包括以下几个关键部分 Unity和虚幻引擎在2D游戏开发中的性能比较 Unity的2D工具设计复杂的地图和场景 创建和管理地图资源&#xff1a; 使用TileMap工具&#xff1a; 构建复杂场景&#xff1a; 添加碰撞体和物理效果&#xff1a; 优化和…

密码访问单页自定义跳转页面源码

源码介绍 密码访问单页自定义跳转页面源码&#xff0c;密码访问单页自定义跳转页面&#xff0c;修改了的密码访问单页&#xff0c;添加了js自定义密码跳转页面。需要正确输入密码才能跳转目标网址。 源码截图 源码下载 密码访问单页自定义跳转页面源码

区分wps还是office创建的文档,word、ppt和excel

手动区分 文档->右键->属性 代码实现 namespace WpsAndOfficeDifferent {internal class Program{static void Main(string[] args){string root System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase ?? "";#region 区分office和wps创建…

SELF-INSTRUCT: Aligning Language Modelswith Self-Generated Instructions 学习

指令微调就是要训练模型执行用户的要求的能力。 文章首先说“指令微调”数据集经常是人工生成&#xff0c;有数量少等缺点。文章提供了一个让语言模型自己生成指令微调数据&#xff0c;自己学习的方法。首先会让一个语言模型自己生成要求&#xff0c;输入和输出&#xff0c;然…

【SpringBoot】电脑商城-09-默认收获地址和删除收货地址

默认收货地址 1 默认收货地址-持久层 1.1 规划需要执行的SQL语句 1.将某用户的所有收货地址设置为非默认地址&#xff08;是否默认&#xff1a;0-不默认&#xff0c;1-默认&#xff09;。 update t_address set is_default0 where uid?2.将某用户指定的收货地址设置为默认…

108页PPT分享:华为流程体系及实施方法最佳实践

PPT下载链接见文末~ 华为的流程体系、流程框架及实施方法是一个复杂而精细的系统&#xff0c;旨在确保公司运作的高效性和竞争力。以下是对这些方面的详细描述&#xff1a; 一、华为的流程体系 华为的流程体系是一套全面的管理体系&#xff0c;它涵盖了企业所有的活动&#…

玩转云服务:Oracle Cloud甲骨文永久免费云主机配置指南(续)

前段时间&#xff0c;和大家分享了白嫖Oracle Cloud的云服务器&#xff1a; 玩转云服务&#xff1a;Oracle Cloud甲骨文永久免费云服务器注册及配置指南。 新注册的小伙伴&#xff0c;可以在 30 天内&#xff0c;利用 300 美元免费储值&#xff0c;任性使用所有 Oracle Cloud …

【unity实战】使用新版输入系统Input System+Rigidbody实现第三人称人物控制器

最终效果 前言 使用CharacterController实现3d角色控制器&#xff0c;之前已经做过很多了&#xff1a; 【unity小技巧】unity最完美的CharacterController 3d角色控制器&#xff0c;实现移动、跳跃、下蹲、奔跑、上下坡、物理碰撞效果&#xff0c;复制粘贴即用 【unity实战】C…

InternLM2.5 部署到安卓手机上

环境准备 1.1 安装rust export RUSTUP_DIST_SERVERhttps://mirrors.ustc.edu.cn/rust-static export RUSTUP_UPDATE_ROOThttps://mirrors.ustc.edu.cn/rust-static/rustup curl --proto https --tlsv1.2 -sSf https://mirrors.ustc.edu.cn/misc/rustup-install.sh | sh1.2 安…

PostgreSQL 服务启动不了问题

如图&#xff0c;遇到这个问题&#xff0c;需要给文件夹打开权限即可。 先给主文件夹postgreSQL打开所有权限,点击属性->安全那里&#xff0c;所有修改啥的权限都打开。再给里面的data文件夹打开权限。

开源搜索引擎之Solr

Apache Solr 是一个开源的企业级搜索平台&#xff0c;构建在 Apache Lucene 之上&#xff0c;提供了强大的全文搜索、实时索引和分布式搜索能力。Solr 被广泛用于构建高性能的搜索应用程序&#xff0c;支持从简单的搜索引擎到复杂的数据分析平台等多种场景。以下是对 Apache So…

1panle搭建的maxkb增加本地向量模型

首先下载模型&#xff0c;比如m3e-large&#xff0c;并上传到/opt/maxkb/model/local_embedding/ 目录&#xff0c;没有就创建 目录如下&#xff1a; 然后修改1panel的容器信息&#xff0c;点击右边的编辑&#xff1a; 在下方的挂在目录处点击添加&#xff1a; 在两个框都输入…

ISIS路由渗透

/ 实验介绍: / 原理概述 在IS-IS网络中&#xff0c;所有的Level-2和Level-1-2路由器构成了一个连续的骨干区域。Level-1区域必须且只能与骨干区域相连&#xff0c;不同的Level-1区域之间不能直接相连。Level-1区域内的路由信息会通过Level-1-2路由器通报给Level-2区域&#x…

EmguCV学习笔记 C# 8.3 Grabcut法

版权声明&#xff1a;本文为博主原创文章&#xff0c;转载请在显著位置标明本文出处以及作者网名&#xff0c;未经作者允许不得用于商业目的。 EmguCV是一个基于OpenCV的开源免费的跨平台计算机视觉库,它向C#和VB.NET开发者提供了OpenCV库的大部分功能。 教程VB.net版本请访问…

爬取央视热榜并存储到MongoDB

1. 环境准备 在开始之前&#xff0c;确保你已经安装了以下Python库&#xff1a; pip install requests pymongo2. 爬取网页内容 首先&#xff0c;我们需要爬取央视热榜的网页内容。通过requests.get()方法&#xff0c;我们可以获取网页的HTML内容&#xff0c;并通过re.finda…

KEYSIGHT是德 Infiniium EXR系列 示波器

Infiniium EXR系列 示波器 苏州新利通 引言 概述 Infiniium EXR系列 出色的信号完整性让信号纤毫毕现 该系列的所有型号都集成了一个 10 位 ADC&#xff0c;并且在所有通道上同时提供 16 GSa/s 的采样率。高分辨率 ADC 的效用取决于示波器的前端底噪是否足够低以提供与之匹…