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

代码随想录(十二)——图论

并查集

并查集主要有三个功能。

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

并查集可以解决的问题:两个节点是否在一个集合,也可以将两个节点添加到一个集合中。

难点在于根的路径压缩的理解

寻找图中是否存在路径 

1971. 寻找图中是否存在路径

有一个具有 n 个顶点的 双向 图,其中每个顶点标记从 0 到 n - 1(包含 0 和 n - 1)。图中的边用一个二维整数数组 edges 表示,其中 edges[i] = [ui, vi] 表示顶点 ui 和顶点 vi 之间的双向边。 每个顶点对由 最多一条 边连接,并且没有顶点存在与自身相连的边。

请你确定是否存在从顶点 source 开始,到顶点 destination 结束的 有效路径 。

给你数组 edges 和整数 nsource 和 destination,如果从 source 到 destination 存在 有效路径 ,则返回 true,否则返回 false 。

class Solution {
public:bool validPath(int n, vector<vector<int>>& edges, int source, int destination) {/*深搜 / 广搜这里选择使用并查集进行实现使用并查集判断两个元素是否在同一个集合内部:step1: 使用join(u,v)把每条边加入到并查集step2: 使用 isSame(int u,int v) 判断是否是同一个根【即是否属于同一个集合】*/// step0: 并查集初始化init(n);// step1: 把每条边加入并查集for(vector<int> edge : edges) { // 每个元素就是一条边join(edge[0],edge[1]);}// step2: 使用 isSame(int u,int v) 判断是否是同一个根return isSame(source, destination);}
private:vector<int> father  = vector<int>(200001,0) ; // 按照节点的大小定义数组长度void init(int n) { // 并查集初始化for(int i = 1; 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 这条边加入并查集 father[v] = uvoid join(int u, int v) {// 先判断两个元素是否在同一个集合内部u = find(u);v = find(v);if(u == v) return;father[v] = u;}
};

冗余连接 

684. 冗余连接

树可以看成是一个连通且 无环 的 无向 图。

给定往一棵 n 个节点 (节点值 1~n) 的树中添加一条边后的图。添加的边的两个顶点包含在 1 到 n 中间,且这条附加的边不属于树中已存在的边。图的信息记录于长度为 n 的二维数组 edges ,edges[i] = [ai, bi] 表示图中在 ai 和 bi 之间存在一条边。

请找出一条可以删去的边,删除后可使得剩余部分是一个有着 n 个节点的树。如果有多个答案,则返回数组 edges 中最后出现的那个。

class Solution {public int[] findRedundantConnection(int[][] edges) {/**图论:删除相对于数来说的多余的一条边使用并查集的思想:把每条边都加入到其中,如果在加入的时候发现两个顶点已经同根;(即在一个并查集中)此时就说明这条边是一条冗余边,删除这条边即可*/int[] ans = null;init(edges.length);for(var edge : edges) {if(!join(edge[0],edge[1])) {ans = edge;break;}}return ans;}private int[] father;private void init(int vLen) { // 并查集的初始化 // 传入顶点数father = new int[vLen+1];for(int i=0; i < vLen; i++) {father[i] = i; // father[i] = i; 自身是自身的根,即刚开始所有节点都是单项的}}// 找到一个元素的根int find(int u) {return father[u] == u ? u: (father[u] = find(father[u]));}// 把 u->v 加入并查集private boolean join(int u, int v) {u = find(u);v = find(v);if(u == v) return false;father[u] = v;return true;}// 判断两个节点是否同根public boolean isSame(int u, int v) {u = find(u);v = find(v);return u == v;}
}

http://www.lryc.cn/news/470023.html

相关文章:

  • 如何通过 Service Mesh 构建高效、安全的微服务系统
  • MySQL 临时表详解
  • Kafka系列之:Kafka集群新增节点后实现数据均衡
  • 实验:使用Oxygen发布大型手册到Word格式
  • 一个基于.NET8+WPF开源的简单的工作流系统
  • MFC工控项目实例二十七添加产品参数
  • PgSQL常用SQL语句
  • python多线程处理xlsx,多进程访问接口
  • PDF无法转换成其他格式的常见原因与解决方法解析
  • 蓝桥杯第二十场小白入门赛
  • K 个一组反转链表
  • #深度学习:从基础到实践
  • Android Kotlin中协程详解
  • 【webpack学习】
  • H5实现PDF文件预览,使用pdf.js-dist进行加载
  • 面试域——面试系统工程
  • PHP-FPM 性能配置优化
  • 渗透测试-百日筑基—SQL注入篇时间注入绕过HTTP数据编码绕过—下
  • Unity - UGUI动静分离
  • arm 体系架构-过程调用约定
  • STM32基于LL库的USART+DMA使用
  • 设计模式06-结构型模式1(适配器/桥接/组合模式/Java)
  • 【损害和风险评估&坑洼】路面坑洼检测系统源码&数据集全套:改进yolo11-DCNV3
  • GenAI 生态系统现状:不止大语言模型和向量数据库
  • gitlab 配置ssh keys
  • 小程序开发实战:PDF转换为图片工具开发
  • 我有两台120kw充电桩一天能赚多少钱
  • 深入了解 Android 中的命名空间:`xmlns:tools` 和其他常见命名空间
  • stable-zero123模型构建指南
  • 算法题解记录32+++最长连续序列(百题筑基)