并查集

/*
* 并查集
* 解决动态连通性一类问题的一种算法
* 在一些有N个元素的集合应用问题中,我们通常是在开始时让每个元素构成一个单元素的集合,
* 然后按一定顺序将属于同一组的元素所在的集合合并,其间要反复查找一个元素在哪个集合中。
* 这里使用并查集解决元素的集合归属的问题。
* 我们让每一个集合成为一个组织,每个组织有一个头目,下面可以分成若干等级。
* 如果两个元素向上找到的头目相同,那么他们就属于同一个组织。
* 就是说每个元素只要知道自己的上级是谁,然后根据上级继续找到头目就能判断是不是属于一个组织。
* 我们规定,当两个人满足同一组织规定的时候,两个人所在的组织也就是同一组织,可以合并起来。
* 这个时候,只需要使得其中一个的组织头目臣服于另一个组织头目就可以了
* 最好的情况下,每一个人都能一步找到头目,这样查找两个人的组织关系的效率是很高的
* 在查找的时候,顺便将查找路径上的人的上级直接定义为组织头目,来压缩路径是很好的办法
* 这里在图的连通的应用中很有价值,比如krustal算法判断点的连通性。
* */
public class _Union_Set_Implement {
    private int size;
    
    //father[i]==i的时候说明 i就是这个组织的头目
    private int[] father;
    private int OriginationNum;

    public _Union_Set_Implement(int size) {
        this.size = size;
        this.OriginationNum = size;
        this.father = new int[this.size];

        for (int i = 0; i < this.size; this.father[i] = i++);

    }

    private int findOrigination(int v) {
        int t;
        for (t = v; this.father[t] != t; t = this.father[t]);

        while (this.father[v] != t) {
            int tt = this.father[v];
            this.father[v] = t;
            v = tt;
        }

        return t;
    }

    public void Merge(int x, int y) {
        int fx = this.findOrigination(x);
        int fy = this.findOrigination(y);
        if (fx != fy) {
            --this.OriginationNum;
            this.father[fx] = fy;
        }
    }
    public boolean isSameOrigination(int x,int y){
        return findOrigination(x)==findOrigination(y);
    }
    public int getOriginationNum() {
        return this.OriginationNum;
    }
}

这里利用并查集来解决一个问题

/*
* 题目详情
* 在地图上给你若干个城镇,这些城镇都可以看作点,然后告诉你哪些对城镇之间是有道路直接相连的。
* 最后要解决的是整幅图的连通性问题。
* 比如随意给你两个点,让你判断它们是否连通,
* 或者问你整幅图一共有几个连通分支,也就是被分成了几个互相独立的块。像畅通工程这题,问还需要修几条路
* 4 2
* 1 3
* 4 3
* */

public class _UnionSet {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        _Union_Set_Implement union=new _Union_Set_Implement(scanner.nextInt());
        int routenum=scanner.nextInt();
        for (int i = 0; i < routenum; i++) {
            int a=scanner.nextInt()-1;
            int b=scanner.nextInt()-1;
            union.Merge(a,b);
        }
        System.out.printf("还需要修建%d条路",union.getOriginationNum()-1);
    }
}
原文地址:https://www.cnblogs.com/Coder-Pig/p/6758498.html