Java - Easy To Understand UNION FIND
\nclass Solution {\n\t// union-find structure\n    class UnionFind {\n        int count;\n        int[] parent;\n        int[] rank;\n        public UnionFind(i
```\nclass Solution {\n\t// union-find structure\n    class UnionFind {\n        int count;\n        int[] parent;\n        int[] rank;\n        public UnionFind(int n) {\n            count = n;\n            parent = new int[n+1];\n            for(int i = 0; i < n+1; i++) {\n                parent[i] = i;\n            }\n            rank = new int[n+1];\n        }\n        \n        public int find(int a) {\n            if(a != parent[a]) {\n                parent[a] = find(parent[a]);\n            }\n            return parent[a];\n        }\n        // returns false if a and b are in same set, i.e., if both have already been reached\n        public boolean union(int a, int b) {\n            int parent_a = find(a);\n            int parent_b = find(b);\n            if(parent_a == parent_b)    return false;\n            if(rank[parent_a] >= rank[parent_b]) {\n                parent[parent_b] = parent_a;\n                if(rank[parent_a] == rank[parent_b])\n                    rank[parent_a]++;\n            }\n            else {\n                parent[parent_a] = parent_b;\n            }\n            count--;\n            return true;\n        }\n            \n        \n    }\n\t// real solution\n    public int maxNumEdgesToRemove(int n, int[][] edges) {\n        UnionFind uf_alice = new UnionFind(n);\n        UnionFind uf_bob = new UnionFind(n);\n        for(int[] edge : edges) {\n            if(edge[0] == 1) {\n                uf_alice.union(edge[1], edge[2]);\n            }\n            else if(edge[0] == 2) {\n                uf_bob.union(edge[1], edge[2]);\n            }\n            else {\n                uf_alice.union(edge[1], edge[2]);\n                uf_bob.union(edge[1], edge[2]);\n            }\n        }\n\t\t// let\'s just make sure, if with given edges they can reach all nodes or not\n        if(uf_alice.count != 1 || uf_bob.count != 1)    return -1;\n        \n\t\t/* okay, so they are reachable , now remove the redundant ones in following way :\n\t\t\t1.  It\'s best to insert the type-3 edges, while removing the redundant ones.\n\t\t\t2.  Once, above step is finished, we can remove the redundant type-1 and redundant type-2 edges. \n\t\t*/\n\t\t\n        uf_alice = new UnionFind(n);\n        uf_bob = new UnionFind(n);\n        int ans = 0;\n        for(int[] edge : edges) {\n            if(edge[0] == 3) {\n                if(!uf_alice.union(edge[1], edge[2]))\n                    ans++;\n                uf_bob.union(edge[1], edge[2]);\n            }\n        }\n        for(int[] edge : edges) {\n            if(edge[0] == 1) {\n                if(!uf_alice.union(edge[1], edge[2]))\n                    ans++;\n            }\n            else if(edge[0] == 2) {\n                if(!uf_bob.union(edge[1], edge[2]))\n                    ans++;\n            }\n        }\n        return ans;\n    }\n}\n```
['Union Find', 'Java']