并查集:互不相交的集合
并查集的3种操作:
(1)Make_Set()
把每一个元素初始化为一个集合,初始化后的每一个元素的父节点是它本身
(2)Find_Set(int x)
查找一个元素所在的集合,关键在于寻找这个元素所在集合的祖先
(3)Union(int x, int y)
合并x和y所在的集合,一个集合的祖先指向另一个集合的祖先
题目:x和y是亲戚,y和z是亲戚,那么x和z也是亲戚。如果x,y是亲戚,那么x的亲戚都是y的亲戚,y的亲戚也都是x的亲戚。先输入10个人(编号从1-10)及7组亲戚关系,然后输入3组数据,问这三组数据是不是亲戚关系?
输入
10 7
2 4
5 7
1 3
8 9
1 2
5 6
2 3
3
3 4
7 10
8 9
输出
Yes
No
Yes
package com.java.study;import java.util.Scanner;public class UnionColl { int [] father; int [] rank; public UnionColl(){} private void Make_Set(){ for(int i = 0 ; i < father.length ; i++){ father[i] = i;//根据实际情况指定的父节点可变化 rank[i] = 0;//根据实际情况初始化秩也有所变化 } } private int Find_Set(int x){ if(x!=father[x]){ father[x] = Find_Set(father[x]);//将查找路径的所有节点都指向根节点 } return father[x]; } void Union(int x, int y){ int f1 = Find_Set(x); int f2 = Find_Set(y); if(f1!=f2){ father[f1] = f2; } } public void go(){ Scanner sc = new Scanner(System.in); int n = sc.nextInt(); int m = sc.nextInt(); father = new int[n+1]; rank = new int[n+1]; Make_Set(); for(int i = 1; i <= m; i++){ int a = sc.nextInt(); int b = sc.nextInt(); int x = Find_Set(a); int y = Find_Set(b); Union(x,y); } int k = sc.nextInt(); for(int i = 1 ; i <= k ;i++){ int x = sc.nextInt(); int y = sc.nextInt(); if(Find_Set(x)==Find_Set(y)) System.out.println("Yes"); else System.out.println("No"); } } public static void main(String[] args) { UnionColl uc = new UnionColl(); uc.go(); }}