zoukankan      html  css  js  c++  java
  • 并查集

    并查集--basic

    public class UnionFind1 {
        private int[] parent;   //数组,表示并查集所有元素的集合号
    
        private int size;   //表示并查集元素个数
    
        public UnionFind1(int size) { //并查集初始化
            this.size = size;
            parent = new int[size];
            for (int i = 0; i < size; i++) {
                parent[i] = i;
            }
        }
    
        /**
         * 查看元素所属集合
         *
         * @param element
         * @return
         */
        private int find(int element) {
            return parent[element];
        }
    
        /**
         * 判断两个集合是否在同一个集合
         *
         * @param firstElement
         * @param secondElement
         * @return
         */
        public boolean isConnected(int firstElement, int secondElement) {
            return find(firstElement) == find(secondElement);
        }
    
        /**
         * 合并firstElement,secondElement两个元素所在集合
         * 将firstElement集合中所有元素的集合号都变为secondElement,就是认为是将两个集合合并
         *
         * @param firstElement
         * @param secondElement
         */
        public void unionElements(int firstElement, int secondElement) {
            int firstUnion = find(firstElement);
            int secondUnion = find(secondElement);
            if (firstUnion != secondUnion) {
                for (int i = 0; i < size; i++) {
                    if (parent[i] == firstUnion) {
                        parent[i] = secondUnion;
                    }
                }
            }
        }
    
        private void printArray() {
            for (int id : this.parent) {
                System.out.print(id + "	");
            }
            System.out.println();
        }
    
        public static void main(String[] args) {
            int n = 10;
            UnionFind1 union = new UnionFind1(n);
            System.out.println("初始:");
            union.printArray();
    
            System.out.println("连接了5 6");
            union.unionElements(5, 6);
            union.printArray();
    
            System.out.println("连接了1 2");
            union.unionElements(1, 2);
            union.printArray();
    
            System.out.println("连接了2 3");
            union.unionElements(2, 3);
            union.printArray();
    
            System.out.println("连接了1 4");
            union.unionElements(1, 4);
            union.printArray();
    
            System.out.println("连接了1 5");
            union.unionElements(1, 5);
            union.printArray();
    
            System.out.println("1  6 是否连接:" + union.isConnected(1, 6));
    
            System.out.println("1  8 是否连接:" + union.isConnected(1, 8));
        }
    }

    快速合并

    public class UnionFind2 {
        private int[] parent;
        private int size;
    
        public UnionFind2(int size) { //初始化并查集
            this.size = size;
            parent = new int[size];
            for (int i = 0; i < size; i++) {
                parent[i] = i;
            }
        }
    
        /**
         * 查找element集合的头结点
         * element=parent[element]:说明element元素是一个集合的头结点或者是自己一个集合
         *
         * @param element
         * @return
         */
        public int find(int element) {
            while (element != parent[element]) {//此时说明element已不是自己一个结点了,所以通过循环找寻element所属集合的头结点
                element = parent[element];
            }
            return element;  //
        }
    
        /**
         * 判断两个元素是否是一个集合:只需要判断两个元素所属集合的头结点是否相同即可
         *
         * @param firstElement
         * @param secondElement
         * @return
         */
        public boolean isConnected(int firstElement, int secondElement) {
            int firstUnion = find(firstElement);
            int secondUnion = find(secondElement);
            return firstUnion == secondUnion;
        }
    
        /**
         * 合并firstElement,secondElement所在的两个集合
         * 将firstElement集合的头结点指向secondElement集合的头结点
         *
         * @param firstElement
         * @param secondElement
         */
        public void unionElements(int firstElement, int secondElement) {
            int firstUnion = find(firstElement);
            int secondUnion = find(secondElement);
            if (firstUnion != secondUnion) {
                parent[firstElement] = secondUnion;
            }
        }
    
        /**
         * 打印每个元素所属集合的小组号,即它的上一个结点号
         */
        private void printArray() {
            for (int parent : parent) {
                System.out.print(parent + " ");
            }
            System.out.println();
        }
    
        public static void main(String[] args) {
            int n = 10;
            UnionFind2 union = new UnionFind2(n);
            System.out.println("初始:");
            union.printArray();
    
            System.out.println("连接了5 6");
            union.unionElements(5, 6);
            union.printArray();
    
            System.out.println("连接了1 2");
            union.unionElements(1, 2);
            union.printArray();
    
            System.out.println("连接了2 3");
            union.unionElements(2, 3);
            union.printArray();
    
            System.out.println("连接了1 4");
            union.unionElements(1, 4);
            union.printArray();
    
            System.out.println("连接了1 5");
            union.unionElements(1, 5);
            union.printArray();
    
            System.out.println("1  6 是否连接:" + union.isConnected(1, 6));
    
            System.out.println("1  8 是否连接:" + union.isConnected(1, 8));
        }
    }  

    快速合并--weight

    public class UnionFind3 {
        private int[] parent;
        private int[] weight;
        private int size;
    
        public UnionFind3(int size) {
            this.parent = new int[size];
            this.weight = new int[size];
            this.size = size;
            for (int i = 0; i < size; i++) {
                this.parent[i] = i;
                this.weight[i] = 1;
            }
        }
    
        /**
         * 查找元素所属集合的头结点
         *
         * @param element
         * @return
         */
        public int find(int element) {
            while (element != parent[element]) {
                element = parent[element];
            }
            return element;
        }
    
        /**
         * 判断两个元素是否是一个集合
         *
         * @param firstElement
         * @param secondElement
         * @return
         */
        public boolean isConnected(int firstElement, int secondElement) {
            return find(firstElement) == find(secondElement);
        }
    
        public void unionElements(int firstElement, int secondElement) {
            int firstRoot = find(firstElement);
            int secondRoot = find(secondElement);
            if (firstRoot == secondRoot) {//已经是同一个集合的元素就不用再合并了
                return;
            }
    
            //集合的子元素多的头结点,合并之后仍然做头结点
            if (weight[firstRoot] > weight[secondRoot]) {
                parent[secondRoot] = firstRoot;
                weight[firstRoot] += weight[secondRoot];
            } else {
                parent[firstRoot] = secondRoot;
                weight[secondRoot] += weight[firstRoot];
            }
        }
    
        /**
         * 打印parent数组
         */
        public void printArray(int[] arr) {
            for (int parent : arr) {
                System.out.print(parent + "	");
            }
            System.out.println();
        }
    
    
        public static void main(String[] args) {
            int n = 10;
            UnionFind3 union = new UnionFind3(n);
    
            System.out.println("初始parent:");
            union.printArray(union.parent);
            System.out.println("初始weight:");
            union.printArray(union.weight);
    
            System.out.println("连接了5 6 之后的parent:");
            union.unionElements(5, 6);
            union.printArray(union.parent);
            System.out.println("连接了5 6 之后的weight:");
            union.printArray(union.weight);
    
            System.out.println("连接了1 2 之后的parent:");
            union.unionElements(1, 2);
            union.printArray(union.parent);
            System.out.println("连接了1 2 之后的weight:");
            union.printArray(union.weight);
    
            System.out.println("连接了2 3 之后的parent:");
            union.unionElements(2, 3);
            union.printArray(union.parent);
            System.out.println("连接了2 3 之后的weight:");
            union.printArray(union.weight);
    
            System.out.println("连接了1 4 之后的parent:");
            union.unionElements(1, 4);
            union.printArray(union.parent);
            System.out.println("连接了1 4 之后的weight:");
            union.printArray(union.weight);
    
            System.out.println("连接了1 5 之后的parent:");
            union.unionElements(1, 5);
            union.printArray(union.parent);
            System.out.println("连接了1 5 之后的weight:");
            union.printArray(union.weight);
    
            System.out.println("1  6 是否连接:" + union.isConnected(1, 6));
    
            System.out.println("1  8 是否连接:" + union.isConnected(1, 8));
        }
    }

    快速合并--height

    public class UnionFind4 {
        private int[] parent;
        private int[] height;
        int size;
    
        public UnionFind4(int size) {
            this.size = size;
            this.parent = new int[size];
            this.height = new int[size];
            for (int i = 0; i < size; i++) {
                parent[i] = i;
                height[i] = 1;
            }
        }
    
        public int find(int element) {
            while (element != parent[element]) {
                element = parent[element];
            }
            return element;
        }
    
        public boolean isConnected(int firstElement, int secondElement) {
            return find(firstElement) == find(secondElement);
    
        }
    
        public void unionElements(int firstElement, int secondElement) {
            int firstRoot = find(firstElement);
            int secondRoot = find(secondElement);
            if (firstRoot == secondRoot) {
                return;
            }
            if (height[firstRoot] > height[secondRoot]) {
                parent[secondRoot] = firstRoot;
            } else if (height[firstRoot] < height[secondRoot]) {
                parent[firstRoot] = secondRoot;
            } else {
                parent[firstRoot] = secondRoot;
                height[secondRoot] += 1;
            }
        }
    
        private void printArray(int[] arr) {
            for (int parent : arr) {
                System.out.print(parent + " ");
            }
            System.out.println();
        }
    
        public static void main(String[] args) {
            int n = 10;
            UnionFind4 union = new UnionFind4(n);
    
            System.out.println("初始parent:");
            union.printArray(union.parent);
            System.out.println("初始height:");
            union.printArray(union.height);
    
            System.out.println("连接了5 6 之后的parent:");
            union.unionElements(5, 6);
            union.printArray(union.parent);
            System.out.println("连接了5 6 之后的height:");
            union.printArray(union.height);
    
            System.out.println("连接了1 2 之后的parent:");
            union.unionElements(1, 2);
            union.printArray(union.parent);
            System.out.println("连接了1 2 之后的height:");
            union.printArray(union.height);
    
            System.out.println("连接了2 3 之后的parent:");
            union.unionElements(2, 3);
            union.printArray(union.parent);
            System.out.println("连接了2 3 之后的height:");
            union.printArray(union.height);
    
            System.out.println("连接了1 4 之后的parent:");
            union.unionElements(1, 4);
            union.printArray(union.parent);
            System.out.println("连接了1 4 之后的height:");
            union.printArray(union.height);
    
            System.out.println("连接了1 5 之后的parent:");
            union.unionElements(1, 5);
            union.printArray(union.parent);
            System.out.println("连接了1 5 之后的height:");
            union.printArray(union.height);
    
            System.out.println("1  6 是否连接:" + union.isConnected(1, 6));
    
            System.out.println("1  8 是否连接:" + union.isConnected(1, 8));
        }
    }

    路径压缩

    public class UnionFind5 {
        private int[] parent;
        private int[] height;
        int size;
    
        public UnionFind5(int size) {
            this.size = size;
            this.parent = new int[size];
            this.height = new int[size];
            for (int i = 0; i < size; i++) {
                parent[i] = i;
                height[i] = 1;
            }
        }
    
        public int find(int element) {
            while (element != parent[element]) {
                parent[element]=parent[parent[element]];//对于height比较大的,可以压缩路径
                element = parent[element];
            }
            return element;
        }
    
        public boolean isConnected(int firstElement, int secondElement) {
            return find(firstElement) == find(secondElement);
    
        }
    
        public void unionElements(int firstElement, int secondElement) {
            int firstRoot = find(firstElement);
            int secondRoot = find(secondElement);
            if (firstRoot == secondRoot) {
                return;
            }
            if (height[firstRoot] > height[secondRoot]) {
                parent[secondRoot] = firstRoot;
            } else if (height[firstRoot] < height[secondRoot]) {
                parent[firstRoot] = secondRoot;
            } else {
                parent[firstRoot] = secondRoot;
                height[secondRoot] += 1;
            }
        }
    
        private void printArray(int[] arr) {
            for (int parent : arr) {
                System.out.print(parent + " ");
            }
            System.out.println();
        }
    
        public static void main(String[] args) {
            int n = 10;
            UnionFind5 union = new UnionFind5(n);
    
            System.out.println("初始parent:");
            union.printArray(union.parent);
            System.out.println("初始height:");
            union.printArray(union.height);
    
            System.out.println("连接了5 6 之后的parent:");
            union.unionElements(5, 6);
            union.printArray(union.parent);
            System.out.println("连接了5 6 之后的height:");
            union.printArray(union.height);
    
            System.out.println("连接了1 2 之后的parent:");
            union.unionElements(1, 2);
            union.printArray(union.parent);
            System.out.println("连接了1 2 之后的height:");
            union.printArray(union.height);
    
            System.out.println("连接了2 3 之后的parent:");
            union.unionElements(2, 3);
            union.printArray(union.parent);
            System.out.println("连接了2 3 之后的height:");
            union.printArray(union.height);
    
            System.out.println("连接了1 4 之后的parent:");
            union.unionElements(1, 4);
            union.printArray(union.parent);
            System.out.println("连接了1 4 之后的height:");
            union.printArray(union.height);
    
            System.out.println("连接了1 5 之后的parent:");
            union.unionElements(1, 5);
            union.printArray(union.parent);
            System.out.println("连接了1 5 之后的height:");
            union.printArray(union.height);
    
            System.out.println("1  6 是否连接:" + union.isConnected(1, 6));
    
            System.out.println("1  8 是否连接:" + union.isConnected(1, 8));
        }
    }

    例题

    例题:How Many Tables

    public class Main {
        private int[] parent;
        private int[] weight;
        private int size;
        private int groups;
    
        public Main(int size) {
            this.size = size;
            this.groups = size;
            this.parent = new int[size];
            this.weight = new int[size];
            for (int i = 0; i < size; i++) {
                parent[i] = i;
                weight[i] = 1;
            }
        }
    
        public int find(int element) {
            while (element != parent[element]) {
                element = parent[element];
            }
            return element;
        }
    
        public boolean isConnected(int firstElement, int secondElement) {
            return find(firstElement) == find(secondElement);
        }
    
        public void unionElement(int firstElement, int secondElement) {
            int firstRoot = find(firstElement);
            int secondRoot = find(secondElement);
            if (firstRoot == secondRoot) {
                return;
            }
            if (weight[firstRoot] < weight[secondRoot]) {
                parent[firstRoot] = secondRoot;
                weight[secondRoot] += weight[firstRoot];
            } else {
                parent[secondRoot] = firstRoot;
                weight[firstRoot] += weight[secondRoot];
            }
            this.groups--;
        }
    
        public int getGroups() {
            return this.groups;
        }
    
        public void printArray(int[] arr) {
            for (int parent : arr) {
                System.out.print(parent + " ");
            }
            System.out.println();
        }
    
        public static void main(String[] args) {
            Scanner scan = new Scanner(System.in);
            int n = scan.nextInt();
            for (int i = 0; i < n; i++) {
                int N = scan.nextInt();
                Main m = new Main(N);
                int M = scan.nextInt();
                for (int j = 0; j < M; j++) {
                    int a = scan.nextInt()-1;
                    int b = scan.nextInt()-1;
                    m.unionElement(a, b);
                }
                System.out.println(m.getGroups());
            }
        }
    }
    

      

  • 相关阅读:
    大白痴学习webmagic
    selenium docs
    centos6.5单用户模式拯救系统
    使用Squid做代理服务器,Squid单网卡透明代理配置详解(转)
    Redundant Call to Object.ToString()
    Specify a culture in string conversion explicitly
    Benefits of Cold Showers: 7 Reasons Why Taking Cool Showers Is Good For Your Health
    Why Creating a Meaningful Morning Routine Will Make You More Successful
    git图示所有分支的历史
    Rewriting History with Git Rebase
  • 原文地址:https://www.cnblogs.com/Hangtutu/p/8025765.html
Copyright © 2011-2022 走看看