并查集题目模板及java代码
Posted 知道什么是码怪吗?
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了并查集题目模板及java代码相关的知识,希望对你有一定的参考价值。
并查集主要用途:
①将两个集合合并
②查询两个元素是否在同一个集合当中
基本原理:
每个集合用一棵树来表示,树根的编号就是整个集合的编号,每个节点存放父节点。
例如:定义一个数组father,father[x]就表示x的父节点。
如何判断是否到达了树根?
if(father[x]==x) // 只有树根的父节点定义为自己的位置
如何求x所处在的集合编号?
while(father[x]!=x) //只要存放的父节点和自身不相等,说明不是父节点
x=father[x]; //然后x跑到父节点的位置
有两个集合father1,father2如何合并两个集合?
//将father1的根节点的父节点值从本身变为father2的根节点。
father1[root1]=root2; //原本father1的根节点的父节点是本身
合并集合
一共有 n个数,编号是 1∼n,最开始每个数各自在一个集合中。
现在要进行 m 个操作,操作共有两种:
M a b
,将编号为 a 和 b 的两个数所在的集合合并,如果两个数已经在同一个集合中,则忽略这个操作;Q a b
,询问编号为 a 和 b 的两个数是否在同一个集合中;
输入格式
第一行输入整数 n 和 m。
接下来 m 行,每行包含一个操作指令,指令为 M a b
或 Q a b
中的一种。
输出格式
对于每个询问指令 Q a b
,都要输出一个结果,如果 a 和 b 在同一集合内,则输出 Yes
,否则输出 No
。
每个结果占一行。
数据范围
1≤n,m≤100000
输入样例:
4 5
M 1 2
M 3 4
Q 1 2
Q 1 3
Q 3 4
输出样例:
Yes
No
Yes
模板代码:
import java.util.*;
public class Main {
static int[] nums = new int[100010];
public static int Find(int number) {// 查找某个数的根节点
// 递归写法+路径压缩。优化过后所有子节点的父节点都指向根节点,加快速度
// if(nums[number]!=number)
// nums[number]=Find(nums[number]);
// return nums[number];
// 普通写法
while (nums[number] != number)// 不相等就继续找
number = nums[number];
return number;
}
public static void Merge(int number1, int number2) {
nums[Find(number1)] = Find(number2);// number1的根节点的父节点指向number2的根节点
}
public static void main(String args[]) {
Scanner input = new Scanner(System.in);
int n = input.nextInt();
int m = input.nextInt();
for (int i = 1; i <= n; i++)
nums[i] = i;
for (int i = 0; i < m; i++) {
String str = input.next();
int number1 = input.nextInt();
int number2 = input.nextInt();
if (str.equals("M"))
Merge(number1, number2);
else if (Find(number1) == Find(number2))
System.out.println("Yes");
else
System.out.println("No");
}
}
}
连通块中点的数量
给定一个包含 n 个点(编号为 1∼n)的无向图,初始时图中没有边。
现在要进行 mm 个操作,操作共有三种:
C a b
,在点 a 和点 b 之间连一条边,aa 和 bb 可能相等;Q1 a b
,询问点 a 和点 b 是否在同一个连通块中,aa 和 bb 可能相等;Q2 a
,询问点 a 所在连通块中点的数量;
输入格式
第一行输入整数 n 和 m。
接下来 m 行,每行包含一个操作指令,指令为 C a b
,Q1 a b
或 Q2 a
中的一种。
输出格式
对于每个询问指令 Q1 a b
,如果 a 和 b 在同一个连通块中,则输出 Yes
,否则输出 No
。
对于每个询问指令 Q2 a
,输出一个整数表示点 a 所在连通块中点的数量
每个结果占一行。
数据范围
1≤n,m≤100000
输入样例:
5 5
C 1 2
Q1 1 2
Q2 1
C 2 5
Q2 5
输出样例:
Yes
2
3
import java.util.*;
public class Main{
static int[] nums=new int[100010];
static int[] count=new int[100010];//记录这个节点所在的集合的节点个数
public static void Connect(int number1,int number2){
int a=Find(number1);//number1的根节点
int b=Find(number2);//number2的根节点
if(a!=b){
nums[a]=b;//number1的根节点的父节点指向number2的根节点
count[b]+=count[a];//更新集合中点的个数
}
}
public static int Find(int number){//查找这个数的根节点
while(nums[number]!=number)
number=nums[number];
return number;
}
public static void main(String args[]){
Scanner input=new Scanner(System.in);
int n=input.nextInt();
int m=input.nextInt();
for(int i=1;i<=n;i++){
nums[i]=i;
count[i]=1;//初始化
}
for(int i=0;i<m;i++){
String str=input.next();
if(str.equals("C")){
int number1=input.nextInt();
int number2=input.nextInt();
Connect(number1,number2);
}
else if(str.equals("Q1")){
int number1=input.nextInt();
int number2=input.nextInt();
if(Find(number1)==Find(number2))
System.out.println("Yes");
else
System.out.println("No");
}
else{
int number=input.nextInt();
System.out.println(count[Find(number)]);
}
}
}
}
以上是关于并查集题目模板及java代码的主要内容,如果未能解决你的问题,请参考以下文章
带权并查集(含种类并查集)经典模板 例题:①POJ 1182 食物链(经典)②HDU - 1829 A bug's life(简单) ③hihoCoder 1515 : 分数调查(示例代码(代