day52 代码随想录算法训练营 图论专题5

1 今日打卡

并查集基础理论 并查集理论基础 | 代码随想录

寻找存在的路线 107. 寻找存在的路线

2 并查集基础理论

当我们需要判断两个元素是否在同一个集合里的时候,我们就要想到用并查集。

模板:

3 寻找存在的路径

3.1 思路

初始化并查集:为每个节点建立独立的集合(父节点指向自己);

合并连通节点:遍历所有边,将每条边的两个节点合并到同一个集合中;

判断连通性:检查目标两个节点是否属于同一个集合(根节点相同),输出结果。

3.2 实现代码

java 复制代码
import java.util.*;

public class Main {
    // 定义并查集内部类,用于管理节点的连通关系
    static class disJoint {
        // 父节点数组:father[i]表示节点i的父节点(静态仅因本题单实例,实际建议去掉static)
        public static int[] father;

        // 并查集构造方法:初始化n个节点的父节点
        public disJoint(int n) {
            // 节点编号从1开始(题目常见输入习惯),数组长度设为n+1
            father = new int[n + 1];
            // 初始化:每个节点的父节点是自己(独立集合)
            for (int i = 0; i <= n; i++) {
                father[i] = i;
            }
        }

        // 查找节点u的根节点(带路径压缩,优化查找效率)
        public int find(int u) {
            // 递归终止条件:u是自己的父节点(u是根节点)
            if (u == father[u]) {
                return u;
            }
            // 路径压缩:将u的父节点直接指向根节点(扁平化树结构)
            father[u] = find(father[u]);
            // 返回压缩后的根节点
            return father[u];
        }

        // 合并两个节点u和v所在的集合
        public void join(int u, int v) {
            // 先找到u的根节点
            u = find(u);
            // 先找到v的根节点
            v = find(v);
            // 如果根节点相同,说明已在同一集合,无需合并
            if (u == v) {
                return;
            }
            // 合并:将v的根节点指向u的根节点(统一集合)
            father[v] = u;
        }

        // 判断两个节点是否在同一个集合(是否连通)
        public boolean isSame(int u, int v) {
            // 找到u的根节点
            u = find(u);
            // 找到v的根节点
            v = find(v);
            // 根节点相同则连通,否则不连通
            return u == v;
        }
    }

    // 主方法:程序入口,处理输入、调用并查集、输出结果
    public static void main(String[] args) {
        // 创建Scanner对象,读取控制台输入
        Scanner sc = new Scanner(System.in);
        // 读取第一个整数n(节点总数),第二个整数m(边的总数)
        int n = sc.nextInt(), m = sc.nextInt();
        // 初始化并查集,容量为n
        disJoint dj = new disJoint(n);

        // 遍历m条边,合并每条边的两个节点
        for (int i = 0; i < m; i++) {
            // 读取当前边的两个节点a和b
            int a = sc.nextInt(), b = sc.nextInt();
            // 合并节点a和b到同一集合
            dj.join(a, b);
        }

        // 读取需要判断连通性的两个节点from和to
        int from = sc.nextInt(), to = sc.nextInt();
        // 判断两个节点是否连通
        if (dj.isSame(from, to)) {
            // 连通则输出1
            System.out.println(1);
        } else {
            // 不连通则输出0
            System.out.println(0);
        }
        // 关闭Scanner,释放资源
        sc.close();
    }
}
相关推荐
OPEN-F18 分钟前
C++20新特性精讲:概念、范围与三路比较
算法·c++20
@MMiL1 小时前
ST-link与J-link通俗易懂讲解
算法
RAOY的AI笔记1 小时前
GPT-6打破孪生素数猜想最新纪录:AI正在进入数学研究新时代?
人工智能·gpt·算法
Nil2081 小时前
leetcode 994腐烂的橘子
算法·leetcode·职场和发展
闻缺陷则喜何志丹1 小时前
【动态规划】P10726 [GESP202406 八级] 空间跳跃|普及+
c++·算法·动态规划·洛谷
嘻哈baby1 小时前
Go 函数中的参数为什么不支持默认值?
java·开发语言·jvm
慧都小项1 小时前
MyEclipse 2026:当 Agent、MCP 与 Java 26 进入 Eclipse 工作流
java·eclipse·springboot·copilot·myeclipse
地平线智能驾驶开发者2 小时前
模型量化入门:从浮点模型到低比特表示
算法·量化·算法工具链
地平线开发者2 小时前
模型量化入门:从浮点模型到低比特表示
算法
CoderYanger2 小时前
前端基础——JavaScript(基础语法)(下篇)
java·开发语言·前端·javascript·程序人生·面试·职场和发展