并查集

首先来明确一下概念,并查集是一种树,主要操作是合并两个集合 以及查询两个结点是否在一个集合中.

虽然这么说但是我总是觉得这是种很奇葩的树.

路径压缩好的并查集的树一般长这样:

对没错就是这样,我没有恶搞,中间是父节点,一圈都是子结点.

这样查询的时候很容易就能判断两个结点是否在一个集合中了(如果两个结点父节点是同一个那么他们就处在一个集合中,反之则不在一个集合中).

并查集最重要路径压缩操作,就是把这个结点父指针指向这个数的根.

public class unionFindSet {
    public static void main(String[] args) {
		int n = 100;
		node[] nodes = new node[100];
		for (int i = 0; i < n; i++) {
			nodes[i] = new node();
			nodes[i].data = i;
			nodes[i].parent = nodes[i];
		}
		union(nodes[1], nodes[2]);
		
    }

    static node findzip(node n) {
        n.parent = find(n);
        return n.parent;
    }

    static node find(node n) {
        if (n.parent == n)
            return n;
        return find(n.parent);
    }

    static void union(node n, node m) {
        node nparent = findzip(n);
        node mparent = findzip(m);
        mparent.parent = nparent;
    }

    static class node {
        int data;
        node parent;
    }
}

最近见到一个bilibili的题:

全宇宙魔法少女大聚会(数量较多),如果魔法少女A和魔法少女B存在羁绊,魔法少女B和魔法少女C存在羁绊,那么魔法少女A和魔法少女C也存在羁绊;所有有羁绊关系的魔法少女形成一个结界,请计算有多少个结界并计算各个结界中的人数。

这道题用并查集就很简单,

import java.util.*;
  
/**
 * 使用并查集把结界建好.
 * 然后用Map统计每个结界中有多少个马猴烧酒
 * Map的大小就是结界的数量
 */
public class UnionFindSet {
  
    public static void main(String[] args) {
  
        int n = 100000;//假设100000个马猴烧酒
        Random random = new Random();
        node[] nodes = new node[n];
        Map<node, Integer> map = new HashMap<>();
  
        for (int i = 0; i < nodes.length; i++) {
            nodes[i] = new node();
            nodes[i].data = random.nextInt(n);//假设100000个马猴烧酒随机存在羁绊
            nodes[i].parent = nodes[i];//初始化它的父指针指向自身
        }
  
        for (int i = 0; i < nodes.length; i++) {
            union(nodes[i], nodes[nodes[i].data]);//建立并查集
        }
  
        for (int i = 0; i < nodes.length; i++) {
            node node = findzip(nodes[i]);
            if (map.containsKey(node)) {
                Integer num = map.get(node) + 1;
                map.put(node, num);
            } else {
                map.put(node, 1);
            }
        }
        System.out.println("共有结界数量: "+map.size());
        Set<node> set = map.keySet();
        for (node node : set) {
            System.out.println("这个结界有马猴烧酒: "+map.get(node));
        }
  
    }
  
  
    static node findzip(node n) {
        n.parent = find(n);
        return n.parent;
    }
  
    static node find(node n) {
        if (n.parent == n)
            return n;
        return find(n.parent);
    }
  
    static void union(node n, node m) {
        node nparent = findzip(n);
        node mparent = findzip(m);
        mparent.parent = nparent;
    }
  
    static class node {
        int data;
        node parent;
    }
}
posted @ 2020-03-10 22:42  continued258  阅读(189)  评论(0)    收藏  举报