news 2026/4/15 13:09:32

【模板】最小生成树(洛谷P3366)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【模板】最小生成树(洛谷P3366)

题目描述

如题,给出一个无向图,求出最小生成树,如果该图不连通,则输出orz

输入格式

第一行包含两个整数 N,M,表示该图共有 N 个结点和 M 条无向边。

接下来 M 行每行包含三个整数 Xi​,Yi​,Zi​,表示有一条长度为 Zi​ 的无向边连接结点 Xi​,Yi​。

输出格式

如果该图连通,则输出一个整数表示最小生成树的各边的长度之和。如果该图不连通则输出orz

输入输出样例

输入 #1复制运行

4 5 1 2 2 1 3 2 1 4 3 2 3 4 3 4 3

输出 #1复制运行

7

说明/提示

数据规模:

对于 20% 的数据,N≤5,M≤20。

对于 40% 的数据,N≤50,M≤2500。

对于 70% 的数据,N≤500,M≤104。

对于 100% 的数据:1≤N≤5000,1≤M≤2×105,1≤Zi​≤104,1≤Xi​,Yi​≤N。

样例解释:

所以最小生成树的总边权为 2+2+3=7。

1. 问题引入

在图论中,最小生成树是一个非常经典的问题:

在一个拥有N个顶点和M条边的带权无向图中,如何找到一棵树,使得它包含所有N个顶点,且所有边的权值之和最小?

此外,还有一个常见变种:如果图本身就是断开的(不连通),我们该如何判断?

本文将基于 Kruskal 算法,结合并查集,给出一种通解。

2. 核心算法:Kruskal (克鲁斯卡尔)

Kruskal 算法的核心思想是“贪心”

算法步骤:

  1. 排序:将所有的边按照权值(w)从小到大排序。我们希望尽可能的选权值小的边。

  2. 遍历:按顺序枚举每一条边(u, v)。

  3. 判断

    • 如果u和v已经在同一个集合里(连通),说明加上这条边会形成环,跳过

    • 如果u和v不在同一个集合,说明这条边连接了两个独立的连通分量,选中它。

    • 将u和v通过并查集合并。

  4. 终止:当我们选够了N-1条边时,最小生成树构建完成。

关键点:连通性判断

如果遍历完所有边,选中的边数仍然小于N-1,说明图是不连通的(有孤岛),此时无法生成 MST,按照题目要求输出 "orz" 。

3. 核心代码解析

3.1 结构体运算符重载

为了方便排序,我们直接在结构体内部重载<运算符。这样调用sort时就不需要写额外的cmp函数,代码封装性更好。

struct edge{ int x,y,w; //重载运算符 让边集数组按照边权从小到大排序 friend bool operator <(edge a,edge b){ return a.w<b.w; } }e[200010];//边集数组 edge mst[5010];//记录最小生成树每条边

3.2 并查集的路径压缩

这是 Kruskal 能高效运行的保证。find函数在递归查找祖先的过程中,直接将沿途节点的父指针指向根节点,将树高度压扁。

int find(int x) { if(fa[x]==x) return x; return fa[x]=find(fa[x]); // 路径压缩,下次查就是 O(1) }

4. 完整代码

//kruskal版 //首先明确什么是不连通,不连通代表图有多个连通分量 //即最后生成最小生成树后所用的边小于n-1(n是节点数) #include <iostream> #include <algorithm>//sort函数头文件 using namespace std; int fa[5010];//并查集 记录每个节点的父/祖先节点(集合中的老大) int n,m;//n个结点 m条无向边 int ans=0;//ans是mst(最小生成树)的边数 记录连了多少条边 //并查集查询+路径压缩 int find(int x){ //如果已经是根结点(集合老大)就返回 if(fa[x]==x) return x; //否则就递归找老大,并把老大给到沿途所有节点 return fa[x]=find(fa[x]); } void uni(int u,int v){ int fau=find(u);//找u老大 int fav=find(v);//找v老大 //如果老大相同就说明已经在一个集合就不需要操作 if(fau!=fav){//如果不同,就让u的老大变成v的老大的老大 fa[fav]=fau; } } struct edge{ int x,y,w; //重载运算符 让边集数组按照边权从小到大排序 friend bool operator <(edge a,edge b){ return a.w<b.w; } }e[200010];//边集数组 edge mst[5010];//记录最小生成树每条边 int main(){ ios::sync_with_stdio(false); cin.tie(0); cin>>n>>m;//n个结点 m条无向边 //初始化每个节点的老大为自己(每个点自己就是一个连通分量) for(int i=1;i<=n;i++) fa[i]=i; //创建边集数组 for(int i=1;i<=m;i++){ cin>>e[i].x>>e[i].y>>e[i].w; } //边集数组按照边权从小到大排序 sort(e+1,e+m+1); int ma=0;//记录最小生成树各边的长度之和 //取每一条边,看这条边的两端是不是同一个连通分量 for(int i=1;i<=m;i++){ int u=e[i].x; int v=e[i].y; //如果u v不连通 就把它两连起来 并把边权加进max //如果已经连通就跳过 if(find(u)!=find(v)){ ans++;//每连一条边 ans+1 //存最小生成树的边(这道题用不到) mst[ans].x=u; mst[ans].y=v; mst[ans].w=e[i].w; uni(u,v);//这条边的两端需要变成一个连通分量(集合) ma+=e[i].w; //最小生成树最多只能有n-1条边 if(ans==n-1) break; } } //如果 连接的边数==节点数-1,说明是连通图 if(ans==n-1) cout<<ma; //不等于 说明有多个连通分量 else cout<<"orz"; return 0; }

5. 总结与易错点

  1. 关于 "orz":Kruskal算法不仅能求最短路径和,还能天然地判断图的连通性。如果循环结束后ans<n-1,说明即使把所有能连的边都连上,图还是断开的。

  2. 数据范围fa数组开N大小,e数组开M大小。不要搞混。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/11 10:13:09

python基于flask框架的健身运动比赛服务饮食推荐平台设计与实现

目录摘要开发技术路线相关技术介绍核心代码参考示例结论源码lw获取/同行可拿货,招校园代理 &#xff1a;文章底部获取博主联系方式&#xff01;摘要 健身运动比赛服务饮食推荐平台基于Flask框架设计&#xff0c;旨在为运动员和健身爱好者提供个性化的饮食建议与赛事服务。平台…

作者头像 李华
网站建设 2026/3/24 4:19:59

炉石传说脚本完整使用指南:从零基础到精通

炉石传说脚本完整使用指南&#xff1a;从零基础到精通 【免费下载链接】Hearthstone-Script Hearthstone script&#xff08;炉石传说脚本&#xff09;&#xff08;2024.01.25停更至国服回归&#xff09; 项目地址: https://gitcode.com/gh_mirrors/he/Hearthstone-Script …

作者头像 李华
网站建设 2026/4/3 8:02:53

RAG优化策略终极指南:17种方法全对比+选型建议,开发者必藏!

文章详细解析了RAG系统的17种优化策略&#xff0c;包括基础检索、语义切分、小块查大块答等方法&#xff0c;对比各策略的检索精度、响应速度和技术成本&#xff0c;并通过GPT评分评估效果。文章提供了基于应用场景和数据特征的选型建议&#xff0c;帮助开发者根据精度需求和预…

作者头像 李华
网站建设 2026/4/7 20:13:27

MySQL数据可视化实战指南

MySQL 数据可视化的基础概念数据可视化与MySQL的关系&#xff1a;MySQL作为数据存储工具&#xff0c;如何为可视化提供结构化数据常见可视化场景&#xff1a;报表、仪表盘、趋势分析等关键工具与技术栈&#xff1a;MySQL 可视化工具&#xff08;如Tableau、Power BI、Metabase…

作者头像 李华
网站建设 2026/4/11 19:28:36

玩转Linux命令:创意组合大赛全攻略

Linux命令创意组合大赛技术文章大纲大赛背景与意义Linux命令组合的灵活性与强大功能 创意组合在实际运维、开发中的价值 大赛对技术社区和技能提升的推动作用参赛要求与规则参赛者需使用基础Linux命令进行组合 禁止使用危险命令&#xff08;如rm -rf /&#xff09; 评判标准&am…

作者头像 李华
网站建设 2026/3/27 17:01:26

如何在3分钟内为Windows 11 LTSC系统安装微软商店:完整指南

如何在3分钟内为Windows 11 LTSC系统安装微软商店&#xff1a;完整指南 【免费下载链接】LTSC-Add-MicrosoftStore Add Windows Store to Windows 11 24H2 LTSC 项目地址: https://gitcode.com/gh_mirrors/ltscad/LTSC-Add-MicrosoftStore 当你在使用Windows 11 LTSC企业…

作者头像 李华