【洛谷P3366】【模板】最小生成树 解题报告

2024-06-23 06:20

本文主要是介绍【洛谷P3366】【模板】最小生成树 解题报告,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

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

题目描述

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

输入格式

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

接下来 M M M 行每行包含三个整数 X i , Y i , Z i X_i,Y_i,Z_i Xi,Yi,Zi,表示有一条长度为 Z i Z_i Zi 的无向边连接结点 X i , Y i X_i,Y_i Xi,Yi

输出格式

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

样例 #1

样例输入 #1

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

样例输出 #1

7

提示

数据规模:

对于 20 % 20\% 20% 的数据, N ≤ 5 N\le 5 N5 M ≤ 20 M\le 20 M20

对于 40 % 40\% 40% 的数据, N ≤ 50 N\le 50 N50 M ≤ 2500 M\le 2500 M2500

对于 70 % 70\% 70% 的数据, N ≤ 500 N\le 500 N500 M ≤ 1 0 4 M\le 10^4 M104

对于 100 % 100\% 100% 的数据: 1 ≤ N ≤ 5000 1\le N\le 5000 1N5000 1 ≤ M ≤ 2 × 1 0 5 1\le M\le 2\times 10^5 1M2×105 1 ≤ Z i ≤ 1 0 4 1\le Z_i \le 10^4 1Zi104

样例解释:

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


前置知识:并查集,最小生成树

这道模板题非常简单,给定一个无向图的各条边以及权值,求最小生成树。可以采用 P r i m Prim Prim算法或者 K r u s k a l Kruskal Kruskal算法。我用的是 K r u s k a l Kruskal Kruskal,因为写起来简单(
基本思路如下:

  • 先读入点数 n n n和边数 m m m,然后用一个结构体数组存放每一条边及其权值,用一个 i n t int int变量 a n s ans ans存放该最小生成树各边的长度之和。
  • 对该结构体使用 C + + C++ C++自带的 S T L STL STL库中的 s o r t ( ) sort() sort()函数,对其进行权值的从小到大的排序。
  • 然后,从权值最小的边开始遍历所有的边,若该边连接的两个顶点不在一个集合内,则使用并查集进行合并,并在 a n s ans ans中加上该边的权值。
  • 最后,再对所有点进行一次遍历,判断是否都在一个集合内以确定该图是否连通。若不连通,输出orz;若连通,则输出 a n s ans ans

以下是100pts的代码:

#define _CRT_SECURE_NO_WARNINGS 1
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;const int MAXN = 5007;//最大点数
const int MAXM = 200007;//最大边数
int n, m;
int f[MAXN];//并查集
struct Node {int x, y, z;
}Arc[MAXM];//边集数组inline int Find(int x) {//并查集寻根&路径压缩return x == f[x] ? x : f[x] = Find(f[x]);
}inline void Merge(int x, int y) {//并查集的合并操作int rx = Find(x), ry = Find(y);if (rx == ry)return;else f[ry] = rx;return;
}inline bool cmp(Node u, Node v) {//结构体排序规则return u.z < v.z;
}inline bool Judge() {//判断所有点是否处于同一集合int Root = Find(1);for (int i = 2; i <= n; ++i)if (Find(i) != Root)return false;return true;
}int main() {cin >> n >> m;for (int i = 1; i <= n; ++i)f[i] = i;//并查集初始化for (int i = 1; i <= m; ++i) cin >> Arc[i].x >> Arc[i].y >> Arc[i].z;sort(Arc + 1, Arc + 1 + m, cmp);//结构体排序,需要的头文件是#include<algorithm>int ans = 0;//存放最小生成树各边的长度之和,int够用for (int i = 1; i <= m; ++i) {//遍历所有边if (Find(Arc[i].x) != Find(Arc[i].y)) {//若顶点x和顶点y不在同一集合Merge(Arc[i].x, Arc[i].y);//合并ans += Arc[i].z;//加上边的权值}}if (!Judge())cout << "orz" << endl;//若图不连通else cout << ans << endl;return 0;
}

完整代码也可以到我的Github查看:传送门


总之就是个非常简单的板子题,适合用来练手。
以上。

这篇关于【洛谷P3366】【模板】最小生成树 解题报告的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

AI一键生成 PPT

AI一键生成 PPT 操作步骤 作为一名打工人,是不是经常需要制作各种PPT来分享我的生活和想法。但是,你们知道,有时候灵感来了,时间却不够用了!😩直到我发现了Kimi AI——一个能够自动生成PPT的神奇助手!🌟 什么是Kimi? 一款月之暗面科技有限公司开发的AI办公工具,帮助用户快速生成高质量的演示文稿。 无论你是职场人士、学生还是教师,Kimi都能够为你的办公文

poj3468(线段树成段更新模板题)

题意:包括两个操作:1、将[a.b]上的数字加上v;2、查询区间[a,b]上的和 下面的介绍是下解题思路: 首先介绍  lazy-tag思想:用一个变量记录每一个线段树节点的变化值,当这部分线段的一致性被破坏我们就将这个变化值传递给子区间,大大增加了线段树的效率。 比如现在需要对[a,b]区间值进行加c操作,那么就从根节点[1,n]开始调用update函数进行操作,如果刚好执行到一个子节点,

C++11第三弹:lambda表达式 | 新的类功能 | 模板的可变参数

🌈个人主页: 南桥几晴秋 🌈C++专栏: 南桥谈C++ 🌈C语言专栏: C语言学习系列 🌈Linux学习专栏: 南桥谈Linux 🌈数据结构学习专栏: 数据结构杂谈 🌈数据库学习专栏: 南桥谈MySQL 🌈Qt学习专栏: 南桥谈Qt 🌈菜鸡代码练习: 练习随想记录 🌈git学习: 南桥谈Git 🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈�

【专题】2024飞行汽车技术全景报告合集PDF分享(附原数据表)

原文链接: https://tecdat.cn/?p=37628 6月16日,小鹏汇天旅航者X2在北京大兴国际机场临空经济区完成首飞,这也是小鹏汇天的产品在京津冀地区进行的首次飞行。小鹏汇天方面还表示,公司准备量产,并计划今年四季度开启预售小鹏汇天分体式飞行汽车,探索分体式飞行汽车城际通勤。阅读原文,获取专题报告合集全文,解锁文末271份飞行汽车相关行业研究报告。 据悉,业内人士对飞行汽车行业

pdfmake生成pdf的使用

实际项目中有时会有根据填写的表单数据或者其他格式的数据,将数据自动填充到pdf文件中根据固定模板生成pdf文件的需求 文章目录 利用pdfmake生成pdf文件1.下载安装pdfmake第三方包2.封装生成pdf文件的共用配置3.生成pdf文件的文件模板内容4.调用方法生成pdf 利用pdfmake生成pdf文件 1.下载安装pdfmake第三方包 npm i pdfma

poj 1258 Agri-Net(最小生成树模板代码)

感觉用这题来当模板更适合。 题意就是给你邻接矩阵求最小生成树啦。~ prim代码:效率很高。172k...0ms。 #include<stdio.h>#include<algorithm>using namespace std;const int MaxN = 101;const int INF = 0x3f3f3f3f;int g[MaxN][MaxN];int n

poj 1287 Networking(prim or kruscal最小生成树)

题意给你点与点间距离,求最小生成树。 注意点是,两点之间可能有不同的路,输入的时候选择最小的,和之前有道最短路WA的题目类似。 prim代码: #include<stdio.h>const int MaxN = 51;const int INF = 0x3f3f3f3f;int g[MaxN][MaxN];int P;int prim(){bool vis[MaxN];

poj 2349 Arctic Network uva 10369(prim or kruscal最小生成树)

题目很麻烦,因为不熟悉最小生成树的算法调试了好久。 感觉网上的题目解释都没说得很清楚,不适合新手。自己写一个。 题意:给你点的坐标,然后两点间可以有两种方式来通信:第一种是卫星通信,第二种是无线电通信。 卫星通信:任何两个有卫星频道的点间都可以直接建立连接,与点间的距离无关; 无线电通信:两个点之间的距离不能超过D,无线电收发器的功率越大,D越大,越昂贵。 计算无线电收发器D

poj 1734 (floyd求最小环并打印路径)

题意: 求图中的一个最小环,并打印路径。 解析: ans 保存最小环长度。 一直wa,最后终于找到原因,inf开太大爆掉了。。。 虽然0x3f3f3f3f用memset好用,但是还是有局限性。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#incl

hdu 1102 uva 10397(最小生成树prim)

hdu 1102: 题意: 给一个邻接矩阵,给一些村庄间已经修的路,问最小生成树。 解析: 把已经修的路的权值改为0,套个prim()。 注意prim 最外层循坏为n-1。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstri