图论:最小生成树

news2025/4/18 7:29:22

最小生成树 (无向无环图)

概念

1.Prim算法 P3366 【模板】最小生成树 - 洛谷

邻接矩阵实现 

#include<iostream>
#include<cstring>
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 5e3 + 10;
int dis[N]; //记录每个结点到其他结点的巨鹿
bool st[N];//记录每个节点是否被遍历过

int edge[N][N];//记录每个结点到其他结点的巨鹿

int n, m;

//prim算法实现
int prim()
{
	//把dis初始化成无穷大
	memset(dis, INF, sizeof(dis));
	dis[1] = 0;//第一个结点开头

	int ret = 0;
	for (int i = 1; i <= n; i++)
	{
		int t = 0;
		//找最近点
		for (int j = 1; j <= n; j++)
		{
			if (!st[j] && dis[j] < dis[t])t = j;//更新最小值的下标
		}
		//判断是否联通
		if (dis[t] == INF)return INF;
		//把该点加进去
		st[t] = true;
		ret += dis[t];
		//更新dis
		for (int i = 1; i <= n; i++)
		{
			if (dis[i] > edge[t][i])//如果距离大于新的结点距离其他节点的距离,更新
				dis[i] = edge[t][i];
		}
	}
	return ret;
}

int main()
{
	cin >> n >> m;
	memset(edge, INF, sizeof(edge));
	for (int i = 1; i <= m; i++)
	{
		int x, y, z; cin >> x >> y >> z;
		//注意有重边的情况,注意是取笑,初始化为无穷大
		edge[x][y] = edge[y][x] = min(edge[x][y], z);
	}
	int ret = prim();
	if (ret == INF)cout << "orz" << endl;
	else
		cout << ret << endl;
}

 vector数组实现


#include<iostream>
#include<cstring>
#include<vector>
using namespace std;

typedef pair<int, int> PII;//连接的点,权值
const int INF = 0x3f3f3f3f;
const int N = 5e3 + 10;

int n, m;
int dis[N];
bool st[N];
vector<PII> dp[N];

int prim()
{
	memset(dis, INF, sizeof(dis));
	dis[1] = 0;
	int ret = 0;

	for (int i = 1; i <= n; i++)//加入n个点,功德圆满
	{
		//找最近的点
		int t = 0;//dis[0]给初始化成INF了
		for (int j = 1; j<= n; j++)
		{
			if (!st[j] && dis[j] < dis[t])//没有被访问过并且比t小,更新t
			{
				t = j;
			}
		}
		//判断是否联通
		if (dis[t] == INF)return INF;
		st[t] = true;
		ret += dis[t];
		//更新dis
		for (auto& x : dp[t])
		{
			int a = x.first;//相连的点
			int b = x.second;//相连的点的权值
			/*if (dis[a] > b)dis[a] = b;*/
			dis[a] = min(dis[a], b);//这里可以解决重边的情况
		}
	}
	return ret;
}

int main()
{
	cin >> n >> m;
	for (int i = 1; i <= m; i++)
	{
		int x, y, z; cin >> x >> y >> z;
		dp[x].push_back({ y,z });
		dp[y].push_back({ x,z });
	}
	int ret = prim();
	if (ret == INF)cout << "orz" << endl;
	else
		cout << ret << endl;
}

2.克鲁斯卡尔算法(并查集实现)

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

#include<iostream>
#include<algorithm>
using namespace std;

const int N = 5010;//点
const int M = 2e5 + 10;//边
const int INF = 0x3f3f3f3f;

struct node
{
	int x, y, z;
}a[M];

int f[N];//并查集
int n, m;

int find(int x)
{
	return f[x] == x ? x : f[x] = find(f[x]);
}
void un(int x, int y)
{
	f[find(x)] = find(y);
}

bool cmp(node& x, node& y)
{
	return x.z < y.z;
}

int kruskal()
{
	int ret = 0;
	int cnt = 0;
	for (int i = 1; i <= m; i++)
	{
		int x = a[i].x, y = a[i].y, z = a[i].z;
		if (find(x) != find(y))//没有并在一起,就整
		{
			cnt++;//记录边的个数,最小生成树,节点数n,边数n-1
			ret += z;
			un(x, y);
		}
	}
	if (cnt != n-1)return INF;//成功的话是n - 1,没有说明不联通
	return ret;
}

int main()
{
	cin >> n >> m;
	for (int i = 1; i <= m; i++)
	{
		cin >> a[i].x >> a[i].y >> a[i].z;
	}
	//并查集初始化
	for (int i = 1; i <= n; i++)f[i] = i;
	//排序,从小到大
	sort(a + 1, a + 1 + m, cmp);
	int ret = kruskal();
	if (ret == INF)cout << "orz" << endl;
	else
		cout << ret << endl;
}

P1194 买礼物 - 洛谷

#include<iostream>
#include<algorithm>
using namespace std;

const int N = 500*500+10;//结点*结点 == 边的个数,我们存的是边的个数
const int M = 1010;
int a, n;//A和节点数
int pos;//有几条边要存
int f[N];//并查集

struct node
{
	int x, y, z;
}b[N];//存边之间的个数

bool cmp(node& x, node& y)//排序
{
	return x.z < y.z;
}

int find(int x)
{
	return f[x] == x ? x : f[x] = find(f[x]);
}
//克鲁斯卡尔算法
int kk()
{
	int ret = 0;//总价
	int cnt = 0;//几条边,用来计算分成几块,有几块就*多少个A
	for (int i = 1; i <= pos; i++)
	{
		int x = b[i].x, y = b[i].y, z = b[i].z;//取出边的数据
		int fx = find(x);
		int fy = find(y);
		if (fx != fy && z < a && z != 0)
		{
			ret += z;
			cnt++;//计算有多少条边
			f[find(x)] = find(y);//合并
		}
	}
	ret += (n - cnt) * a;//有几块树
	return ret;
}

int main()
{
	cin >> a >> n;
	for (int i = 1; i <= n; i++)
	{
		for (int j = 1; j <= n; j++)
		{
			int k; cin >> k;
			//只需要存一条边的关系
            //但其实就算不要也无所谓,因为并查集合并后,也不会要重复的
            //克鲁斯卡尔算法只需要存取,边的数据就好了,不重复更好
			if (i >= j)continue;
			pos++;
			b[pos].x = i, b[pos].y = j, b[pos].z = k;
		}
	}
	for (int i = 1; i <= n; i++)f[i] = i;

	sort(b + 1, b + 1 + pos,cmp);

	int ret = kk();
	cout << ret << endl;
}


P2330 [SCOI2005] 繁忙的都市 - 洛谷

瓶颈树:生成所有生成树中,最大边权值最小的那棵树。

也就是最小生成树。

最小生成树的最大边值也就是最终结果

#include<iostream>
#include<algorithm>
using namespace std;

const int N = 310;
const int M = 8010;
int n, m;
int pos;
int f[N];

struct node
{
	int x, y, z;
}a[M];

int find(int x)
{
	return f[x] == x ? x : f[x] = find(f[x]);
}

bool cmp(node& x, node& y)
{
	return x.z < y.z;
}

int ret = 0;
void kk()
{
	for (int i = 1; i <= m; i++)
	{
		int x = a[i].x, y = a[i].y, z = a[i].z;
		int fx = find(x), fy = find(y);
		if (fx != fy)
		{
			ret = max(ret, z);
			f[fx] = fy;
		}
	}
}

int main()
{
	cin >> n >> m;
	for (int i = 1; i <= m; i++)
	{
		int x, y, z;
		cin >> x >> y >> z;
		a[i].x = x, a[i].y = y, a[i].z = z;
	}
	cout << n - 1 << " ";
	for (int i = 1; i <= n; i++)f[i] = i;
	sort(a + 1, a + 1 + m, cmp);
	kk();
	cout << ret << endl;
}

P2573 [SCOI2012] 滑雪 - 洛谷

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;

typedef long long LL;

const int N = 1e5 + 10;
const int M = 2e6 + 10;//考虑两重变

typedef pair<int, int> PII;//可以到的点,到该点的距离

int n, m;//n个景点,m条边
int h[N];//每个景点的高度

vector<PII> dp[N];//记录该点可以去的所有的点+到的距离

bool st[N];
LL cnt;//记录有多少个景点被访问了
int pos;//记录有多少条边

struct node
{
	int x, y, z;
}a[M];//记录边的数据

int f[N];//并查集

void dfs(int u)//找所有可以到达的边
{
	cnt++;
	st[u] = true;
	for (auto& s : dp[u])//遍历该点可以到达的每一条边,并且进行记录
	{
		int x = s.first, y = s.second;
		++pos;//多一条边
		a[pos].x = u, a[pos].y = x, a[pos].z = y;
		if (!st[x])//没有被访问过
		{
			dfs(x);
		}
	}
}
bool cmp(node& x, node& y)//从该点到宁一个点的高的优先,其次是距离
{
	int x1 = x.x, y1 = x.y, z1 = x.z;
	int x2 = y.x, y2 = y.y, z2 = y.z;
	if (h[y1] != h[y2])return h[y1] > h[y2];
	return z1 < z2;
}

int find(int x)
{
	return f[x] == x ? x : f[x] = find(f[x]);
}

LL ret;
void kk()
{
	sort(a + 1, a + 1 + pos, cmp);
	for (int i = 1; i <= n; i++)f[i] = i;

	for (int i = 1; i <= pos; i++)
	{
		int x = a[i].x, y = a[i].y, z = a[i].z;
		int fx = find(x);
		int fy = find(y);
		if (fx != fy)
		{
			ret += z;
			f[fx] = fy;
		}
	}

}

int main()
{
	cin >> n >> m;
	for (int i = 1; i <= n; i++)cin >> h[i];

	for (int i = 1; i <= m; i++)
	{
		int x, y, z; cin >> x >> y >> z;
		if (h[x] >= h[y])dp[x].push_back({ y,z });
		if (h[y] >= h[x])dp[y].push_back({ x,z });//如果是 == 的话,那么两边的都要记录
	}
	dfs(1);
	
	kk();
	cout << cnt << " "<<ret << endl;
}


有向图:

由于克鲁斯卡尔算法要把所有的边进行排序没所以我们要创建一个起点,终点,边的结构体

题目没有明确给出那就自己创建。

dfs:把所有的路径都找到。(遍历到一条边就加入路径)
用胶囊把所有可以到的点统计到。->生成最小生成树。

最小生成树:利用dfs找到的路径据生成最小生成树
距离最短->所有距离的总和。--->最小生成树。

选边的时候,优先去往高的位置的边,其次才是距离

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

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

相关文章

rqlite:一个基于SQLite构建的分布式数据库

今天给大家介绍一个基于 SQLite 构建的轻量级分布式关系型数据库&#xff1a;rqlite。 rqlite 基于 Raft 协议&#xff0c;结合了 SQLite 的简洁性以及高可用分布式系统的稳健性&#xff0c;对开发者友好&#xff0c;操作极其简便&#xff0c;其核心设计理念是以最低的复杂度实…

Dynamics 365 Business Central Recurring Sales Lines 经常购买销售行 来作 订阅

#D365 BC ERP# #Navision# 前面有节文章专门介绍了BC 2024 Wave 2 支持的更好的Substription & Recurring Billing。 其实在D365 BC ERP中一直有一个比较简单的订阅模块Recrring Sales Lines。本文将介绍一下如何用Recurring Sales Lines来 实施简易的订阅Substription。具…

探索生成式AI在游戏开发中的应用——3D角色生成式 AI 实现

概述 自从开创性论文 Denoising Diffusion Probabilistic Models 发布以来&#xff0c;此类图像生成器一直在改进&#xff0c;生成的图像质量在多个指标上都击败了 GAN&#xff0c;并且与真实图像无法区分。 NeRF: Representing Scenes as Neural Radiance Fields for View S…

K8s 老鸟的配置管理避雷手册

Yining, China 引言 对于这种案例&#xff0c;你们的处理思路是怎么样的呢&#xff0c;是否真正的处理过&#xff0c;如果遇到&#xff0c;你们应该怎么处理。 最后有相关的学习群&#xff0c;有兴趣可以加入。 开始 一、血泪教训&#xff1a;环境变量引发的真实灾难 1.1 …

3-Visual Studio 2022打包NET开发项目为安装包

引言 本文将上一期博文>>>门店管理系统开发<<<开发的项目打包为Windows安装包 一&#xff0c;安装扩展 安装此扩展&#xff1a;installer Projects 二&#xff0c;创建安装程序项目 创建项目 右键解决方案-添加-新建项目 选择setup Project项目 填写项目名…

国内外网络安全政策动态(2025年3月)

▶︎ 1.《关于进一步加强智能网联汽车产品准入、召回及软件在线升级管理的通知》发布 3月1日&#xff0c;工业和信息化部、市场监管总局联合发布《关于进一步加强智能网联汽车产品准入、召回及软件在线升级管理的通知》&#xff08;以下简称《通知》&#xff09;。 该通知旨在…

已知Word内容格式固定,通过宏实现Word转Excel

文章目录 需求描述一、宏是什么&#xff1f;二、使用步骤1.启用开发工具2.VBA基础知识3.单个Word文件转为Excel4.批量将Word文件转为Excel文件 总结 需求描述 现在有多个Word文档&#xff0c;Word文档格式固定&#xff0c;假如Word内容分为单选题和多选题&#xff0c;每个题目…

SpringDoc【使用详解】

SpringDoc使用详解 一、何为SpringDoc二、概念解释三、SpringDoc使用2.1简单集成2.2 配置SpringDoc2.2.1 yml方式配置2.2.2配置文档信息 2.3配置文档分组2.4使用注解2.4.1 Tag2.4.2 Operation2.4.3 Schema2.4.4 NotNull2.4.5 Parameter2.4.6 Parameters2.4.7 ApiResponses 和Ap…

Redis持久化 | RDB AOF | 常见问题

目录 RDB&#xff08;Redis DataBase&#xff09; 给什么内存数据做快照——&#xff08;全量&#xff09; 触发机制 RDB文件生成的时候会阻塞主线程吗&#xff1f; 关闭持久化命令 bgsave执行流程 RDB文件怎么配置&#xff1f;有哪些优缺点 优点&#xff1a; 缺点&am…

React 列表渲染

开发环境&#xff1a;Reacttsantd 你可能经常需要通过 JavaScript 的数组方法 来操作数组中的数据&#xff0c;从而将一个数据集渲染成多个相似的组件。在这篇文章中&#xff0c;你将学会如何在 React 中使用 filter() 筛选需要渲染的组件和使用 map() 把数组转换成组件数组。 …

[ctfshow web入门] web25

信息收集 要想拿到flag&#xff0c;需要突破两层if。 解题 第一个if 传入r0&#xff0c;拿到mt_rand的值&#xff0c;由于每一次访问都会重新设置种子&#xff0c;所以每一次访问都是一样的随机数。 所以我们的r mt_rand-显示的值 1799250188 r1799250188就可以突破第一…

【数据结构】树的介绍

目录 一、树1.1什么是树&#xff1f;1.2 树的概念与结构1.3树的相关术语1.4 树形结构实际运用场景 二、二叉树2.1 概念与结构2.2 特殊的二叉树2.2.1 满二叉树2.2.2 完全二叉树 个人主页&#xff0c;点击这里~ 数据结构专栏&#xff0c;点击这里~ 一、树 1.1什么是树&#xff1…

Android源码之App启动

目录 App启动概述 App启动过程 App启动过程图 源码概述 跨进程启动 进程内启动 下面以应用桌面Launcher启动App的MainActivity来举例&#xff1a; App启动概述 首先&#xff0c;MainActivity是由Launcher组件来启动的&#xff0c;而Launcher又是通过Activity管理服务Act…

【GESP】C++二级练习 luogu-B3721 [语言月赛202303] Stone Gambling S

GESP二级练习&#xff0c;多层循环分支练习&#xff0c;难度★✮☆☆☆。 题目题解详见&#xff1a;https://www.coderli.com/gesp-2-luogu-b3721/ 【GESP】C二级练习 luogu-B3721 [语言月赛202303] Stone Gambling S | OneCoderGESP二级练习&#xff0c;多层循环分支练习&am…

2. Qt界面文件原理

本节主要介绍ui文件如何与窗口关联&#xff0c;并通过隐式连接方式显示对话框 本文部分ppt、视频截图原链接&#xff1a;[萌马工作室的个人空间-萌马工作室个人主页-哔哩哔哩视频] 1 UI文件如何与窗口关联 1.1 mainwindow.cpp的头文件ui_mainwindow.h 根据编译原理的基本规…

Elastic 的 OpenTelemetry 分发版(EDOT)现已正式发布:开源、可用于生产环境的 OTel

作者&#xff1a;来自 Elastic Miguel Luna 及 Bahubali Shetti Elastic 自豪地宣布正式发布 Elastic OpenTelemetry 分发版&#xff08;Elastic Distributions of OpenTelemetry - EDOT&#xff09;&#xff0c;其中包含 Elastic 自定义版本的 OpenTelemetry Collector 以及多…

docker部署jenkins并成功自动化部署微服务

一、环境版本清单&#xff1a; docker 26.1.4JDK 17.0.28Mysql 8.0.27Redis 6.0.5nacos 2.5.1maven 3.8.8jenkins 2.492.2 二、服务架构&#xff1a;有gateway&#xff0c;archives&#xff0c;system这三个服务 三、部署步骤 四、安装linux 五、在linux上安装redis&#…

【NLP 53、投机采样加速推理】

目录 一、投机采样 二、投机采样改进&#xff1a;美杜莎模型 流程 改进 三、Deepseek的投机采样 流程 Ⅰ、输入文本预处理 Ⅱ、引导模型预测 Ⅲ、候选集筛选&#xff08;可选&#xff09; Ⅳ、主模型验证 Ⅴ、生成输出与循环 骗你的&#xff0c;其实我在意透了 —— 25.4.4 一、…

VScode连接CentOS 7.6虚拟机

本文内容&#xff1a;在Windows上使用VMware运行虚拟机&#xff0c;然后使用VScode连接CentOS 7.6虚拟机。 进入系统前 安装VMware 安装教程参考&#xff1a;VMware安装 下载CentOS 7.6镜像 可以使用国内镜像源&#xff0c;但是一般国内镜像源要么已经不维护CentOS 7.6这个…