java-代码随想录第55天|并查集理论基础、107. 寻找存在的路线

目录

并查集理论基础

107. 寻找存在的路线


学习链接:并查集理论基础 | 代码随想录

并查集理论基础

可以解决什么问题呢?

        并查集常用来解决连通性问题。大白话就是当我们需要判断两个元素是否在同一个集合里的时候,我们就要想到用并查集。

        我们将三个元素A,B,C (分别是数字)放在同一个集合,其实就是将三个元素连通在一起,如何连通呢?只需要用一个一维数组来表示,即:father[A] = B,father[B] = C 这样就表述 A 与 B 与 C连通了(有向连通图)。

        如何表示 C 也在同一个元素里呢? 我们需要 father[C] = C,即C的根也为C,这样就方便表示 A,B,C 都在同一个集合里了。

        所以father数组初始化的时候要 father[i] = i,默认自己指向自己。

并查集主要有两个功能

        1.将两个元素添加到一个集合中。

        2.判断两个元素在不在同一个集合

代码模板

//并查集模板
class DisJoint{
    private int[] father;
    //并查集初始化
    public DisJoint(int N) {
        father = new int[N];
        for (int i = 0; i < N; ++i){
            father[i] = i;
        }
    }
    //并查集里寻找根的过程
    //使用路径压缩 father[n] = find(father[n]
    public int find(int n) {
        return n == father[n] ? n : (father[n] = find(father[n]));
    }
    //将n->m这条边加入并查集
    public void join (int n, int m) {
        n = find(n);
        m = find(m);
        if (n == m) return;
        father[m] = n;
    }
    //判断n和m是否找到同一个根
    public boolean isSame(int n, int m){
        n = find(n);
        m = find(m);
        return n == m;
    }
 
}

通过模板,我们可以知道,并查集主要有三个功能。

1.寻找根节点,函数:find(int u),也就是判断这个节点的祖先节点是哪个

2.将两个节点接入到同一个集合,函数:join(int u, int v),将两个节点连在同一个根节点上

3.判断两个节点是否在同一个集合,函数:isSame(int u, int v),就是判断两个节点是不是同一个根节点

107. 寻找存在的路线

题目描述

        给定一个包含 n 个节点的无向图中,节点编号从 1 到 n (含 1 和 n )。

        你的任务是判断是否有一条从节点 source 出发到节点 destination 的路径存在。

输入描述

        第一行包含两个正整数 N 和 M,N 代表节点的个数,M 代表边的个数。 

        后续 M 行,每行两个正整数 s 和 t,代表从节点 s 与节点 t 之间有一条边。 

        最后一行包含两个正整数,代表起始节点 source 和目标节点 destination。

输出描述

        输出一个整数,代表是否存在从节点 source 到节点 destination 的路径。如果存在,输出 1;否则,输出 0。

题解:

        1.1234在同一个集合中,5不在这个集合中

        2.判断起始节点和终止节点是否在同一个集合里

import java.util.*;
 
public class Main{
    public static void main(String[] args) {
        int N, M;
        Scanner scanner = new Scanner(System.in);
        N = scanner.nextInt();
        M = scanner.nextInt();
        DisJoint disJoint = new DisJoint(N + 1);
        //加入到并查集中
        for (int i = 0; i < M; ++i) {
            disJoint.join(scanner.nextInt(), scanner.nextInt());
        }
        //判断起始节点和终止节点是否相同
        if(disJoint.isSame(scanner.nextInt(), scanner.nextInt())) {
            //如果相同则输出1
            System.out.println("1");
        } else {
            System.out.println("0");
        }
    }
 
}

//并查集模板
class DisJoint{
    private int[] father;
 
    public DisJoint(int N) {
        father = new int[N];
        for (int i = 0; i < N; ++i){
            father[i] = i;
        }
    }
 
    public int find(int n) {
        return n == father[n] ? n : (father[n] = find(father[n]));
    }
 
    public void join (int n, int m) {
        n = find(n);
        m = find(m);
        if (n == m) return;
        father[m] = n;
    }
 
    public boolean isSame(int n, int m){
        n = find(n);
        m = find(m);
        return n == m;
    }
 
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值