当前位置: 首页 > news >正文

算法训练营day55 图论⑤ 并查集理论基础、107. 寻找存在的路径

        本篇博客介绍并查集这种数据结构组织方法,以及适合解决的问题,理解并查集的很好的方法是跟着博客链接中的模拟步骤推导一遍

并查集理论基础

        并查集常用来解决连通性问题。大白话就是当我们需要判断两个元素是否在同一个集合里的时候,我们就要想到用并查集。

        并查集主要有两个功能:

  • 将两个元素添加到一个集合中。
  • 判断两个元素在不在同一个集合

        原理:通过数据结构(数组)连接同一集合元素

        路径压缩:将非根节点的所有节点直接指向根节点。

代码模板

        通过模板,我们可以知道,并查集主要有三个功能。注意对于“寻根”的理解

  1. 寻找根节点,函数:find(int u),也就是判断这个节点的祖先节点是哪个
  2. 将两个节点接入到同一个集合,函数:join(int u, int v),将两个节点连在同一个根节点上
  3. 判断两个节点是否在同一个集合,函数:isSame(int u, int v),就是判断两个节点是不是同一个根节点

并查集模拟过程        

int n = 1005; // n根据题目中节点数量而定,一般比节点数量大一点就好
vector<int> father = vector<int> (n, 0); // C++里的一种数组结构// 并查集初始化
void init() {for (int i = 0; i < n; ++i) {father[i] = i;}
}
// 并查集里寻根的过程
int find(int u) {return u == father[u] ? u : father[u] = find(father[u]); // 路径压缩
}// 判断 u 和 v是否找到同一个根
bool isSame(int u, int v) {u = find(u);v = find(v);return u == v;
}// 将v->u 这条边加入并查集
void join(int u, int v) {u = find(u); // 寻找u的根v = find(v); // 寻找v的根if (u == v) return ; // 如果发现根相同,则说明在一个集合,不用两个节点相连直接返回father[v] = u;
}

优化思路

        其实还有另一种方法:按秩(rank)合并。rank表示树的高度,即树中结点层次的最大值。但是很显而易见,这种合并方式不如之前的方式平缓,所以增益不是很显著

107. 寻找存在的路径

        并查集主要解决集合问题,即:两个节点在不在一个集合,也可以将两个节点添加到一个集合中

        成体不难,核心在于理解并查集的关键成员函数

class UnionFind:def __init__(self, size):self.parent = list(range(size + 1))  # 初始化并查集
# range(size + 1) 生成一个从 0 到 size 的整数序列(包含 size 本身)
# list(range(size + 1)) 将这个序列转换为列表def find(self, u):if self.parent[u] != u:self.parent[u] = self.find(self.parent[u])  # 路径压缩return self.parent[u]def union(self, u, v):root_u = self.find(u)root_v = self.find(v)if root_u != root_v:self.parent[root_v] = root_udef is_same(self, u, v):return self.find(u) == self.find(v)def main():import sysinput = sys.stdin.readdata = input().split()index = 0n = int(data[index])index += 1m = int(data[index])index += 1uf = UnionFind(n)for _ in range(m):s = int(data[index])index += 1t = int(data[index])index += 1uf.union(s, t)source = int(data[index])index += 1destination = int(data[index])if uf.is_same(source, destination):print(1)else:print(0)if __name__ == "__main__":main()

http://www.dtcms.com/a/338721.html

相关文章:

  • 谷歌为什么要将Android的页面大小(Page Size)从传统的4KB升级至16KB
  • 解决 UniApp 自定义弹框被图片或 Canvas 覆盖的 Bug
  • 云原生俱乐部-mysql知识点归纳(3)
  • 2 . 大纲
  • 常用植被物候提取方法 (TIMESATE/R语言/Python)-4.0
  • QChart智能坐标轴
  • 【3-3】流量控制与差错控制
  • Linux的ALSA音频框架学习笔记
  • 为单片机专门定制的Unicode字库和API接口
  • 18650锂电池自动化生产线:智能集成提升制造效能
  • Datawhale工作流自动化平台n8n入门教程(一):n8n简介与平台部署
  • 机器学习深度学习 所需数据的清洗实战案例 (结构清晰、万字解析、完整代码)包括机器学习方法预测缺失值的实践
  • 基于 PyTorch 模型训练优化、FastAPI 跨域配置与 Vue 响应式交互的手写数字识别
  • 【Qt】线程池与全局信号实现异步协作
  • 【qml-5】qml与c++交互(类型单例)
  • JVM垃圾收集器
  • Linux重置 root 密码:从原理到实操
  • 免费OCR工具支持哪些文档格式转换
  • 8.19打卡 DAY 46 通道注意力(SE注意力)
  • RPC高频问题与底层原理剖析
  • 在VSCode中进行Vue前端开发推荐的插件
  • 基于C语言基础对C++的进一步学习_知识补充、组合类、类中的静态成员与静态函数、类中的常对象和常成员函数、类中的this指针、类中的友元
  • Laya的适配模式选择
  • 使用 Ansys Discovery 探索外部空气动力学
  • 龙虎榜——20250819
  • python学习打卡day38
  • 上网行为管理-内容审计
  • 初识CNN05——经典网络认识2
  • GPT-5 上线风波深度复盘:从口碑两极到策略调整,OpenAI 的变与不变
  • 006.Redis 哨兵(Sentinel)架构实战