[Java] Mega easy solution to understand
The algorithm: \n0. Initialize count as number of total edges n\n1. Since the type 3 is applicable for both Alice and Bob, consider only those edges. It is opti
The algorithm: \n0. Initialize `count` as number of total edges `n`\n1. Since the type 3 is applicable for both Alice and Bob, consider only those edges. It is optimal.\n2. Create a copy for `parent` and `rank`\n3. Continue merging only Bob edges. If they are already connected, do not consider them, decrement count.\n4. Use the copy to instantiate the DisjointSet\'s `parent` and `rank`.\n5. Continue merging only Alice edges. If they are already connected, do not consider them, decrement count. \n6. Return `n-cnt`  which is the `total number of edges` - `necessary number of edges`\n\nP.S. Hope it helped, your likes would be appreciated)\n\n```\nclass Solution {\n    class DisjointSet {\n        int[] parent;\n        int[] rank;\n        int n;\n        \n        public DisjointSet(int n) {\n            this.n = n;\n            parent = new int[n+1];\n            rank = new int[n+1];\n            for (int i = 1; i <= n; i++) {\n                parent[i] = i;\n            }\n        }\n        \n        public int find(int node) {\n            while (node != parent[node])\n                node = parent[node];\n            \n            return node;\n        }\n        \n        public boolean merge(int a, int b) {\n            int parentA = find(a);\n            int parentB = find(b);\n            \n            if (parentA == parentB) return false;\n            \n            if (rank[parentA] >= rank[parentB]) {\n                parent[parentB] = parentA;\n                rank[parentA]++;\n            } else {\n                parent[parentA] = parentB;\n                rank[parentB]++;\n            }\n            \n            return true;\n        }\n        \n        public int countSeparateComponents() {\n            int cnt = 0;\n            \n            for (int i = 1; i <= n; i++) \n                if (parent[i] == i) \n                    cnt++;\n            \n            return cnt;\n        }\n    }\n    \n    public int maxNumEdgesToRemove(int n, int[][] edges) {\n        DisjointSet ds = new DisjointSet(n);\n        int cnt = n;\n        \n        for (int[] e : edges) {\n            if (e[0] == 3) {\n                boolean status = ds.merge(e[1], e[2]);\n                if (!status) cnt--;\n            }\n        }\n        \n        int[] parentCopy = new int[n+1];\n        int[] rankCopy = new int[n+1];\n        for (int i = 1; i <= n; i++) {\n            parentCopy[i] = ds.parent[i];\n            rankCopy[i] = ds.rank[i];\n        }\n        \n        // Let\'s run for Bob only\n        for (int[] e : edges) {\n            if (e[0] == 2) {\n                boolean status = ds.merge(e[1], e[2]);\n                if (!status) cnt--;\n            }\n        }\n        \n        if (ds.countSeparateComponents() > 1) {\n            return -1;\n        } \n        \n        ds.parent = parentCopy;\n        ds.rank = rankCopy;\n        \n        // Let\'s run for Alice only\n        for (int[] e : edges) {\n            if (e[0] == 1) {\n                boolean status = ds.merge(e[1], e[2]);\n                if (!status) cnt--;\n            }\n        }\n        \n        if (ds.countSeparateComponents() > 1) {\n            return -1;\n        } \n        \n        return n-cnt;\n    }\n}\n```
['Union Find', 'Java']