并查集
算法适用
给定一些操作,查找联通块/查找集合数/查找环的个数
节点初始化
创建一维数组,大小为n+1,数组索引代表节点名,数组值代表指向节点
查找父节点
若当前节点指向自身,为根节点,找到并返回
否则,顺着指向的节点(数组索引位置的值)继续寻找
链接节点,合并集合
1 2 3
| int a_value=find(a); int b_value=find(b); num[a_value]=b_value;
|
若根节点相同,可以不连接
同时,若根节点相同,说明图中出现了环
路径压缩
本质是存储搜索的结果
1 2 3 4 5 6 7
| public int find(int a) { if (num[a]==a) return a; else { num[a]=find(num[a]); return num[a]; } }
|
返回集合个数
指向自身的节点为一个集合的父节点,统计数组值等于自身的节点个数
应用实例
经典并查集题目合根植物
一道搜索题,也可以用并查集来解细胞数量
使用面向对象的形式封装好
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| import java.util.*; public class 手搓并查集 { public static class bcj{ static int num[]; public bcj(int n) { num=new int[n+1]; for (int i = 1; i <=n; i++) { num[i]=i; } } public int find(int a) { if (num[a]==a) return a; else { num[a]=find(num[a]); return num[a]; } } public void add(int a,int b) { int a_value=find(a); int b_value=find(b); num[a_value]=b_value; } public int sumnode() { int ans=0; for (int i = 1; i < num.length; i++) { if(num[i]==i) ans++; } return ans; } } public static void main(String[] args) { Scanner scan=new Scanner(System.in); bcj a=new bcj(scan.nextInt()*scan.nextInt()); int N=scan.nextInt(); for (int i = 0; i < N; i++) { a.add(scan.nextInt(), scan.nextInt()); } System.out.println(a.sumnode()); scan.close(); } }
|