并查集
java
// 1.初始化
int fa[MAXN];
void init(int n)
{
for (int i=1;i<=n;++i)
fa[i]=i;
}
// 2.查询
找到的祖先直接返回,未进行路径压缩
int.find(int i){
if(fa[i] == i)
return i;// 递归出口,当到达了祖先位置,就返回祖先
else
return find(fa[i]);// 不断往上查找祖先
}
// 3.合并
void unionn(int i,int j)
int i_fa=find(i);// 找到i的祖先
int j_fa=find(j);// 找到j的祖先
fa[i_fa]=j_fa;// i的祖先指向j的祖先。
}
路径压缩,也就是在某一次find函数执行过程中,更新子节点的指向,直接指向顶级节点
107.寻找存在的路径
题目:107. 寻找存在的路径 (kamacoder.com)
思路:难道说,使用并查集的find函数,遍历所有的边,将节点的父亲信息存起来,如果source和destination没有指向同一个根节点,那么就说明不存在路径
尝试(不对)
java
import java.util.*;
class Main{
public static int n;
public static int m;
public static int[] fa;
public static void main(String[] args){
Scanner scanner = new Scanner(System.in);
n = scanner.nextInt();
m = scanner.nextInt();
fa = new int[n];
for(int i = 0; i<n; i++){
fa[i] = i;
}
for(int i = 0; i<m; i++){
int n1 = scanner.nextInt();
int n2 = scanner.nextInt();
union(n1,n2);
}
int source = scanner.nextInt();
int destination = scanner.nextInt();
if(source == find(destination)){
System.out.println(1);
}else{
System.out.println(0);
}
}
public static void union(int i , int j){
int i_fa = find(i);
int j_fa = find(j);
fa[i_fa] = j_fa;
}
public static int find(int j){
if(j==fa[j])
return j;
else{
fa[j] = find(fa[j]);
return fa[j];
}
}
}
答案
java
import java.util.Scanner;
public class Main {
private static int[] father;
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt(); // 节点数量
int m = scanner.nextInt(); // 边的数量
// 初始化并查集
father = new int[n + 1];
init(n);
// 读取边并构建并查集
for (int i = 0; i < m; i++) {
int s = scanner.nextInt();
int t = scanner.nextInt();
join(s, t);
}
int source = scanner.nextInt(); // 起始节点
int destination = scanner.nextInt(); // 目标节点
// 判断是否在同一个集合中
if (isSame(source, destination)) {
System.out.println(1);
} else {
System.out.println(0);
}
}
// 并查集初始化
private static void init(int n) {
for (int i = 1; i <= n; i++) {
father[i] = i;
}
}
// 并查集里寻根的过程
private static int find(int u) {
if (u != father[u]) {
father[u] = find(father[u]);
}
return father[u];
}
// 判断 u 和 v 是否找到同一个根
private static boolean isSame(int u, int v) {
return find(u) == find(v);
}
// 将 v -> u 这条边加入并查集
private static void join(int u, int v) {
int rootU = find(u);
int rootV = find(v);
if (rootU != rootV) {
father[rootV] = rootU;
}
}
}