并查集【合并 Union、查询 Find】

并查集(Disjoint-set data structure):不交集数据结构

处理一些不交集(Disjoint sets,一系列没有重复元素的集合)和合并与查询

1. 并查集支持的操作

1.1 查询

查询某个元素属于哪个集合,通常返回集内的一个 ”代表元素“。===> 为了判断2个元素是否在同一集合中

1.2 合并

将2个集合合并成一个

1.3 添加

添加一个新集合,其中有一个新元素

Union方法:让2个原本不相交的集合,让其相交 ===> 在这2个集合中选出一个新的老大

  • 原来 0 是集合1的老大,5是集合2的老大
  • 现在我们指定0为最终的新老大,那么原来的5就得改成0了
    现在要建立 0 --> 5 的联系,这时注意:我们不能直接将 3 指向 5,而是先找到 3 的老大 0 ,让0 去指向 5

习题

297. We are a Team

import java.util.Scanner;
import java.util.*;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    static int[] arr;

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();   //  n 个人
        int m = in.nextInt();   //  m 条消息
        if (n < 1 || n >= 100000 || m < 1 || m >= 100000){
            System.out.println("NULL");
            return;
        }
        arr = new int[n + 1];
        for (int i = 0; i < arr.length; i++) {
            arr[i] = i;
        }

        for (int i = 0; i < m; i++) {
            int a = in.nextInt();
            int b = in.nextInt();
            int c = in.nextInt();
            if (!isValid(a, b, c, n)){
                System.out.println("da pian zi");
                continue;
            }
            if (c == 0){
                union(a, b);
                continue;
            }
            if (find(a) == find(b)){
                System.out.println("we are a team");
                continue;
            }
            System.out.println("we are not a team");
        }
    }

     public static int find(int x){
        if (x == arr[x]){
            return x;
        }
        return arr[x] = find(arr[x]);
    }

    public static void union(int x, int y){
        int f1 = find(x);
        int f2 = find(y);
        if (f1 != f2){
            arr[f2] = f1;
        }
    }

    public static boolean isValid(int a, int b, int c, int n){
        if (c != 1 && c != 0){
            return false;
        }
        if (a < 1 || a > n){
            return false;
        }
        if (b < 1 || b > n){
            return false;
        }
        return true;
    }
}

231. 图像物体的边界【解像素1是否联通的并查集求解 ===> 双重循环】

import java.util.Scanner;
import java.util.*;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    static int[][] arr;
    static int[] temp;
    static int[][] offsets = {{0, 1}, {1, 1}, {1, 0}, {1, -1}, {0, -1}, {-1, -1}, {-1, 0}, {-1, 1}};

    public static void main(String[] args) {
       Scanner in = new Scanner(System.in);
        int row = in.nextInt();
        int col = in.nextInt();
        arr = new int[row][col];
        int res = 0;
        List<Dir> list = new ArrayList<>();
        for (int i = 0; i < row; i++) {
            for (int j = 0; j < col; j++) {
                arr[i][j] = in.nextInt();
            }
        }

        for (int i = 0; i < row; i++) {
            for (int j = 0; j < col; j++) {
                if (arr[i][j] == 5){
                    for (int[] offset : offsets) {
                        int x = i + offset[0];
                        int y = j + offset[1];
                        if (x >= 0 && x < row && y >= 0 && y < col && arr[x][y] == 1){
                            list.add(new Dir(x, y));
                            res++;
                        }
                    }
                }
            }
        }
        temp = new int[res];
        for (int i = 0; i < temp.length; i++) {
            temp[i] = i;
        }
        for (int i = 0; i < list.size(); i++) {
            Dir dir1 = list.get(i);
            for (int j = i + 1; j < list.size(); j++) {
                Dir dir2 = list.get(j);
                if (union(dir1.x, dir1.y, dir2.x, dir2.y, i, j)){
                    res--;
                }
            }
        }
        System.out.println(res);
    }
     public static int find(int x){
        if (x == temp[x]){
            return x;
        }
        return find(temp[x]);
    }

    public static boolean union(int x1, int y1, int x2, int y2, int order1, int order2){
        if (Math.abs(x1 - x2) <= 1 && Math.abs(y1 - y2) <= 1){
            int f1 = find(order1);
            int f2 = find(order2);
            if (f1 != f2){
                temp[f2] = f1;
                return true;
            }
        }
        return false;
    }
}

class Dir{
    int x;
    int y;

    public Dir(int x, int y) {
        this.x = x;
        this.y = y;
    }
}
posted @ 2023-09-09 13:08  爱新觉罗LQ  阅读(36)  评论(0编辑  收藏  举报