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

news2024/10/7 2:25:14

题目描述

如题,给出一个无向图,求出最小生成树,如果该图不连通,则输出 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×10^5,1≤Zi​≤10^4。

样例解释:

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

 本题考察最小身成树的构造,两种解法,普里姆(prim)算法和克鲁斯卡尔(kruskal)算法

两种算法的时间复杂度分别为O(n^2)和O(e*loge),n为顶点数,e为边数,本题两种解法,题目范围可知消耗时间差不多

普里姆(prim)算法

普里姆(prim)算法的思想是任取一顶点为其起始点,选择与起始点相连的边中权值最小的一个作为生成树的边,然后在从这条边的另一个点和起始点的所有边选一条权值最小的边,重复如此,选择的边的另一个点必须是没有在树中。

思路如上,普里姆一般用邻接矩阵,判断是否为连通图只需要dfs遍历一次,若是连通图,dfs遍历一次就能将所有点标记

#include<stdio.h>
int a[5001][5001];
void vie(int x)//无向图初始化
{
	for (int i = 1; i <= x; i++)
		for (int j = i; j <= x; j++)
		{
			if (i == j)
				a[i][j] = 0;
			else
			{
				a[j][i] = 1e9;
				a[i][j] = 1e9;
			}
		}
}
int book[5001], n;
void dfs(int x)//dfs遍历图
{
	book[x] = 1;
	for (int i = 1; i <= n; i++)
		if (a[x][i] < 1e9 && book[i] == 0)
			dfs(i);
}
int main()
{
	int m, i, j, x, y, z;
	scanf("%d %d", &n, &m);
	vie(n);//初始化邻接矩阵
	for (i = 1; i <= m; i++)//输入边
	{
		scanf("%d %d %d", &x, &y, &z);
		if(a[x][y]>z)
		{
			a[x][y] = z;
			a[y][x] = z;
		}
	}
	dfs(1);//判断是否为连通图
	for (i = 1; i <= n; i++)
	{
		if (book[i] == 0)//存在没有遍历到的点,不是连通图
		{
			printf("orz");
			return 0;
		}
	}
	int dis[5001];//松弛数组
	for (i = 1; i <= n; i++)//初始化以1作为起始点
		dis[i] = a[1][i];
	int sum = 0;//统计最小各个长度和
	for (i = 2; i <= n; i++)//n个结点,需要构造n-1条边
	{
		int min = 1e9, k = 0;
		for (j = 2; j <= n; j++)//寻找最小权值的边,第1个点已经确定不用判断
		{
			if (dis[j] != 0 && min > dis[j])
			{
				min = dis[j]; k = j;
			}
		}
		sum += min;//加上该边的权值
		dis[k] = 0;
		for (j = 1; j <= n; j++)
			if (dis[j] > a[k][j])
				dis[j] = a[k][j];
	}
	printf("%d", sum);
	return 0;
}

克鲁斯卡尔(kruskal)算法

 克鲁斯卡尔(kruskal)算法的思想是每次选择权值最小的边,前提是这条边的两个顶点之间没有  联系,每次选权值最小的边好办,对边进行排序,判断两个点是否有联系,可以用并查集,对于边提前用边集数组储存,根据权值进行排序,选n-1条边结束

这题用 克鲁斯卡尔(kruskal)算法解决对于这题判断图是否是连通图只需要判断并查集数组里面有几个老大,若是超过1则不是连通图。

#include<stdio.h>
struct nb {
	int l, r, data;
}a[200001];//结构体数组储存每条边的信息
int n, m, ss[5001];//ss为并查集数组
void kp(int x, int y)//快速排序
{
	if (x >= y)return;
	int left = x, right = y;
	struct nb temp = a[x], t;
	while (left < right)
	{
		while (a[right].data >= temp.data && left < right)
			right--;
		while (a[left].data <= temp.data && left < right)
			left++;
		if (left < right)
		{
			t = a[left]; a[left] = a[right]; a[right] = t;
		}
	}
	a[x] = a[left]; a[left] = temp;
	kp(x, left - 1);
	kp(left + 1, y);
}
int find(int x)//寻找x点的老大
{
	if (ss[x] == 0)
		return x;
	else
	{
		ss[x] = find(ss[x]);//路径压缩
		return ss[x];
	}
}
int bing(int x, int y)//判断x,y的老大是否为同一个,是的话返回0
{
	int t1 = find(x);//x的老大
	int t2 = find(y);//y的老大
	if (t1 != t2)
	{
		ss[t1] = t2;
		return 1;
	}
	return 0;
}
int main()
{
	int i, j;
	scanf("%d %d", &n, &m);
	for (i = 1; i <= m; i++)
		scanf("%d %d %d", &a[i].l, &a[i].r, &a[i].data);//输入边
	kp(1, m);//升序排序
	int sum = 0, count = 0;
	for (i = 1; i <= m; i++)
	{
		if (bing(a[i].l, a[i].r))//如果边的两点没有联系
		{
			sum += a[i].data;//统计边权值的和
			count++;//最小生成树边的数量加1
		}
		if (count == n - 1)//选到n-1条边后直接结束
			break;
	}
	int kk = 0;
	for (i = 1; i <= n; i++)//寻找老大数量
		if (ss[i] == 0)
			kk++;
	if (kk > 1)//超过1不是连通图,不能生成树
		printf("orz");
	else
		printf("%d", sum);
	return 0;
}

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

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

相关文章

力扣题目训练(6)

2024年1月30日力扣题目训练 2024年1月30日力扣题目训练367. 有效的完全平方数374. 猜数字大小383. 赎金信99. 恢复二叉搜索树105. 从前序与中序遍历序列构造二叉树51. N 皇后 2024年1月30日力扣题目训练 2024年1月30日第六天编程训练&#xff0c;今天主要是进行一些题训练&…

1 月 30 日算法练习-思维和贪心

文章目录 重复字符串翻硬币乘积最大 重复字符串 思路&#xff1a;判断是否能整除&#xff0c;如果不能整除直接退出&#xff0c;能整除每次从每组对应位置中找出出现最多的字母将其他值修改为它&#xff0c;所有修改次数即为答案。 #include<iostream> using namespace …

太美医疗冲刺港交所上市:融资“数据打架”,老虎基金提前退出

1月29日&#xff0c;浙江太美医疗科技股份有限公司&#xff08;下称“太美医疗”或“太美医疗科技”&#xff09;递交招股书&#xff0c;准备在港交所主板上市。特别说明的是&#xff0c;该公司曾于2021年12月29日在上海证券交易所科创板递交上市申请。 据贝多财经了解&#x…

容器算法迭代器初识

#include<iostream> using namespace std; #include<vector> //vetor容器存放内置数据类型 void test01() {//创建了一个vector容器&#xff0c;数组 vector<int> v;//向容器中插入数据v.push_back (10);//尾插 v.push_back (20);v.push_back (30);v.push_ba…

vue-Router 路由

一、什么是路由&#xff1f; 在Web开发中&#xff0c;路由&#xff08;Routing&#xff09;是指根据用户访问的URL来决定应用程序应该显示哪个页面或者加载哪个组件的过程。简单来说&#xff0c;路由就是将不同的URL映射到不同的功能模块或页面上。当用户点击链接或者直接输入…

ADI 配合 USRP 使用的相控阵天线 cn0566

相控阵天线 在这里插入图片描述

利用Excel批量生成SQL语句

根据对应的数据库结构书写模板SQL&#xff0c;如&#xff1a; INSERT INTO Person VALUES(1,吕布,25,男,13500000001)然后选择表格后的单元格&#xff0c;并复制SQL语句&#xff08;注意最前方有一个号&#xff0c;整个SQL用 “ ” 包裹&#xff09;&#xff1a; "INSER…

响应式Web开发项目教程(HTML5+CSS3+Bootstrap)第2版 例5-5 Canvas 绘制三角形

代码 <!doctype html> <html> <head> <meta charset"utf-8"> <title>Canvas 绘制三角形</title> </head><body><canvas id"cavsElem">您的浏览器不支持Canvas&#xff0c;请升级浏览器</canvas…

墨鱼AI导航系统源码/小白也能即拿即用+视频教程

(购买本专栏可免费下载栏目内所有资源不受限制,持续发布中,需要注意的是,本专栏为批量下载专用,并无法保证某款源码或者插件绝对可用,介意不要购买) 墨鱼AI导航源码/小白也能即拿即用+视频教程,AI目前大火,估计未来3年内都将是风口。本系统墨鱼AI导航,顺着AI的风口,…

【Godot4自学手册】第十节将场景添加到TileSet绘制背景,主人公走到房子后面房子变得半透明

这节主要学习将场景添加到TileSet作为TileMap来搭建背景。同时&#xff0c;主人公进入房子后面&#xff0c;房子变得半透明&#xff0c;离开房子后房子变的不透明。 一、创建新场景 首先导入房子素材&#xff0c;最终文件系统内容如下&#xff1a; 点击新建场景按钮&#x…

Origin 2022下载安装教程,操作简单,小白也能轻松搞定,附安装包,带软件使用教程

前言 Origin是一个科学绘图、数据分析软件&#xff0c;支持各种各样的2D/3D图形&#xff0c;包括统计&#xff0c;信号处理&#xff0c;曲线拟合以及峰值分析&#xff0c;Origin具有强大的数据导入功能和多样的图形输出格式。 准备工作 1、Win7及以上系统 2、提前准备好 Or…

标注数据集 --labelimg

前言&#xff1a;我们想要训练自己的数据集时&#xff0c;通常需要自己标注数据集。无论是标注成yolo可识别的txt格式还是voc数据集的xml格式。使用labelimg标注都是一个不错的选择。 下面我们就从创建环境&#xff0c;使用labelimg进行标注两个方面来说明。 1.创建labelimg环境…

flutter 五点一点五:MaterialApp Theme一堆主题

一堆主题 大部分都是统一设置组件的默认样式的主题 具体属性基本上与相关组件一致 具体再学习组件时 说明 IconThemeData? iconTheme, // 设置icon的颜色 Appbar中的icon无效 IconThemeData primaryIconTheme, // 与primaryColor形成对比的图标主题IconThemeData accentIconT…

arcgis 如何计算线的长度和面的面积

一、线要素长度计算 1.打开线shp图层&#xff0c;右键图层-打开属性表&#xff08;CtrlT&#xff09; 2.在表选项里选添加字段 添加成功后&#xff0c;属性表多了一个新添加的字段 3.右键点击长度选择计算几何 二、面要素面积计算 面积计算跟长度计算一样&#xff0c;…

linux jenkins相关命令

1.jenkins启动命令 [rootlocalhost /]#service jenkins start 2.jenkins停止命令 [rootlocalhost /]#service jenkins stop 3.查询jenkins状态命令 [rootlocalhost /]#service jenkins status 4.重启jenkins命令 [rootlocalhost /]#service jenkins restart Jenkins默认的端口号…

WINDOWS中电源设置小工具

你可以使用WinPowerSet&#xff0c;玩CS2之前&#xff0c;把电源设置为“高性能”&#xff0c;玩后设置为“平衡”。 WinPowerSet 下载地址&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1iOp29c4ica9L47t_l9lZ2w?pwdd248 提取码&#xff1a;d248 最近新配了一台12…

flutter 搜索框实现,键盘搜索按钮,清空,防抖

import package:flutter/material.dart; import package:flutter_screenutil/flutter_screenutil.dart; import package:flutter_svg/svg.dart; import package:sy_project/config/app_colors.dart; import package:sy_project/core/assets.dart;/// 搜索textview class Custom…

Qt 基础之QDataTime

Qt 基础之QDataTime 引言一、获取(设定)日期和时间二、时间戳三、时间计算 (重载运算符) 引言 QDataTime是Qt框架中用于处理日期和时间的类。它提供了操作和格式化日期、时间和日期时间组合的功能。QDataTime可以用于存储和检索日期和时间、比较日期和时间、对日期和时间执行算…

C语言字符串操作函数详解①strlen函数的讲解与三种模拟实现方法(建议三连收藏)

目录 ​编辑 前言 1.strlen函数介绍 2.模拟实现strlen 2.1计数器做法 2.2不创建临时变量&#xff0c;通过递归的方法 2.3利用两个指针相减 3.结语 前言 C语言中对字符和字符串的处理很是频繁&#xff0c;但是C语言本身是没有字符串类型的&#xff0c;字符串通常放在常量…

DC-磁盘配额(23国赛真题)

2023全国职业院校技能大赛网络系统管理赛项–模块B&#xff1a;服务部署&#xff08;WindowServer2022&#xff09; 文章目录 DC-磁盘配额题目配置步骤验证查看DC2驱动器C:\的磁盘配额&#xff0c;限制磁盘空间&#xff0c;警告等级等配置 DC-磁盘配额 题目 在DC2驱动器C:\上…