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();
    }
}
相关推荐
考虑考虑5 小时前
Mybatis实现批量插入
java·后端·mybatis
咖啡八杯6 小时前
GoF设计模式——中介者模式
java·后端·spring·设计模式
青石路10 小时前
记一次多JDK版本问题的排查,一坑套一坑,差点没爬上来
java
先吃饱再说11 小时前
判断回文字符串,从一行代码到双指针优化
算法
像我这样帅的人丶你还13 小时前
Java 后端详解(五):Redis 缓存
java·后端·全栈
黄敬峰14 小时前
深入理解算法核心:从递归思想、数组扁平化到快速排序
算法
plainGeekDev15 小时前
GreenDAO → Room
android·java·kotlin
得物技术15 小时前
从狂野代码到按目标生产:得物推荐 AI Harness 的工程化实践|AICon 演讲整理
人工智能·算法·架构
AI小老六19 小时前
SkillOpt 架构拆解:把 Skill 文本当参数,用执行轨迹训练 Agent
后端·算法·ai编程