目录
学习链接:并查集理论基础 | 代码随想录
并查集理论基础
可以解决什么问题呢?
并查集常用来解决连通性问题。大白话就是当我们需要判断两个元素是否在同一个集合里的时候,我们就要想到用并查集。
我们将三个元素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;
}
}

被折叠的 条评论
为什么被折叠?



