并查集算法

本文详细介绍了并查集算法的关键思想、核心函数find()和merge()的逻辑,并通过一个实例展示了如何利用并查集解决圈子问题,找出最大圈子的人数。通过Java代码实现,对输入的用户关系进行处理,最终输出最大圈子的人数。
摘要由CSDN通过智能技术生成

并查集算法

关键思想

fa[i] = j, 表示i节点的父节点为j,初始状态下,fa[i] = i, 表示父节点为自己

关键函数

  1. find()方法

    逻辑如下:查看x节点父节点是否为自己,若是返回x,若不是则递归调用find(fa[x])去寻找该集合下的根节点root

     int find(int x)
     {
         return x == fa[x] ? x : (fa[x] = find(fa[x]));
     }
  2. merge()方法

    主要逻辑为:找到i、j节点的根节点,将两者建立关联

    rank[i]表示i节点的深度(整体呈树形结构)

    若x的深度小于等于y,则将y作为x的父节点

    反之,x作为y的父节点。如果两边树的深度相同,则y节点深度➕1

     void merge(int i, int j)
     {
         int x = find(i), y = find(j);
         if (rank[x] <= rank[y])
             fa[x] = y;
         else
             fa[y] = x;
         if (rank[x] == rank[y] && x != y)
             rank[y]++;
     }

例题

import java.util.*;
 ​
 /**
  * 现在有107个用户,编号为1- 107,现在已知有m对关系,每一对关系给你两个数x和y,代表编号为x的用户和编号为y的用户是在一个圈子中,例如:A和B在一个圈子中,B和C在一个圈子中,那么A,B,C就在一个圈子中。现在想知道最多的一个圈子内有多少个用户。 
  *
  * 输入描述:
  * 第一行输入一个整数T,接下来有T组测试数据。
  * 对于每一组测试数据:第一行输入1个整数n,代表有n对关系。
  * 接下来n行,每一行输入两个数x和y,代表编号为x和编号为y的用户在同一个圈子里。
  * 1 ≤ T ≤ 10
  * 1 ≤ n ≤ 105
  * 1 ≤ x, y ≤ 107
  *
  * 输出描述:
  * 对于每组数据,输出一个答案代表一个圈子内的最多人数
  */
 class Solution1 {
     static class Relation {
         int x, y;
 ​
         Relation(int x, int y) {
             this.x = x;
             this.y = y;
         }
     }
 ​
 ​
     static Map<Integer, Integer> map = new HashMap<>();
 ​
     public static int find(int x) {
         if (x == map.get(x)) {
             return x;
         } else {
             int rootNode = find(map.get(x));
             map.put(x, rootNode);
             return rootNode;
         }
     }
 ​
     public static void merge(int i, int j) {
         int x = find(i), y = find(j);
         map.put(x, y); // y as root node
     }
 ​
     public static void main(String[] args) {
         Scanner scanner = new Scanner(System.in);
         int t = scanner.nextInt();
         for (int i = 0; i < t; i++) {
             int n = scanner.nextInt();
             int x, y;
             map.clear();
             ArrayList<Relation> arrayList = new ArrayList<>();
             for (int j = 0; j < n; j++) {
                 x = scanner.nextInt();
                 y = scanner.nextInt();
                 arrayList.add(new Relation(x, y));
                 map.put(x, x);
                 map.put(y, y);
             }
 ​
             for (Relation relation : arrayList) {
                 merge(relation.x, relation.y);
             }
             Map<Integer, Integer> countMap = new HashMap<>();
             Iterator<Map.Entry<Integer, Integer>> iterator = map.entrySet().iterator();
             for (; iterator.hasNext(); ) {
                 int root = find(iterator.next().getValue());
                 int cur = countMap.getOrDefault(root, 0);
                 countMap.put(root, cur + 1);
             }
             int max = Integer.MIN_VALUE;
             for (Map.Entry<Integer, Integer> entry : countMap.entrySet()) {
                 if (entry.getValue() > max) max = entry.getValue();
             }
             System.out.println(max);
         }
     }
 }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值