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();
    }
}
相关推荐
lay_liu21 小时前
springboot 文件下载
java·spring boot·后端
Flittly21 小时前
【SpringAIAlibaba新手村系列】(11)Embedding 向量化与向量数据库
java·笔记·spring·ai·springboot
Darkwanderor21 小时前
什么数据量适合用什么算法
c++·算法
workflower21 小时前
AI制造-推荐初始步骤
java·开发语言·人工智能·软件工程·制造·需求分析·软件需求
zc.ovo21 小时前
河北师范大学2026校赛题解(A,E,I)
c++·算法
py有趣21 小时前
力扣热门100题之环形链表
算法·leetcode·链表
py有趣21 小时前
力扣热门100题之回文链表
算法·leetcode·链表
ACGkaka_1 天前
SimpleDateFormat 线程安全问题及修复方案
java·jvm·安全