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();
    }
}
相关推荐
FakeOccupational15 分钟前
【数学 密码学】量子通信:光的偏振&极化的量子不确定性特性 + 量子密钥分发 BB84算法步骤
算法·密码学
呱牛do it1 小时前
企业级门户网站设计与实现:基于SpringBoot + Vue3的全栈解决方案(Day 3)
java·vue
ZhengEnCi2 小时前
S10-蓝桥杯 17822 乐乐的积木塔
算法
神の愛2 小时前
左连接查询数据 left join
java·服务器·前端
贾斯汀玛尔斯2 小时前
每天学一个算法--拓扑排序(Topological Sort)
算法·深度优先
大龄程序员狗哥2 小时前
第25篇:Q-Learning算法解析——强化学习中的经典“价值”学习(原理解析)
人工智能·学习·算法
exp_add32 小时前
质数相关知识
算法
南境十里·墨染春水3 小时前
linux学习进展 线程同步——互斥锁
java·linux·学习
雨奔3 小时前
Kubernetes 联邦 Deployment 指南:跨集群统一管理 Pod
java·容器·kubernetes
杨凯凡3 小时前
【021】反射与注解:Spring 里背后的影子
java·后端·spring