Easy to understand C++ solution using DSU
Code\n\nclass DSU {\npublic:\n    vector<int> parent;\n    vector<int> rank;\n    int components;\n\n    DSU(int n) {\n        parent.resize(n+1);\n        for(
# Code\n```\nclass DSU {\npublic:\n    vector<int> parent;\n    vector<int> rank;\n    int components;\n\n    DSU(int n) {\n        parent.resize(n+1);\n        for(int i = 1; i <=n; i++) {\n            parent[i] = i;\n        }\n        rank.resize(n+1);\n        components = n;\n    }\n\n    int findParent(int node) {\n        if(node == parent[node]) {\n            return node;\n        }\n        return findParent(parent[node]);\n    }\n\n    void unionByRank(int node1, int node2) {\n        int p1 = findParent(node1);\n        int p2 = findParent(node2);\n\n        if(p1 == p2) {\n            return;\n        }\n        if(rank[p1] > rank[p2]) {\n            parent[p2] = p1;\n        } else if(rank[p2] > rank[p1]) {\n            parent[p1] = p2;\n        } else {\n            parent[p1] = p2;\n            rank[p2]++;\n        }\n        components--;\n    }\n\n    bool isSingle() {\n        return components == 1;\n    }\n\n};\n\nclass Solution {\npublic:\n   \n    int maxNumEdgesToRemove(int n, vector<vector<int>>& edges) {\n        // Aaj bhi DSU ka question hai\n        // 2 DSU Banao Alice and Bob k liye\n        // aur edges ko traverse karo sorting order me type k 3,2,1\n        // agr type 3 hai to u and v k parent check karo agr wo \n        // alag hai to union karo aur edge++ karo ye kaam dono k liye karo\n        // agr type 2 hai aur u and v ka parent same nahi to union karo aur\n        // edge++ karo, same kaam type 1 k liye bhi\n        // last me check karo ki agr components dono graph ka 1 hai to\n        // return edges.size() - edge otherwise return -1;\n        DSU Alice(n);\n        DSU Bob(n);\n\n        auto lambda = [](vector<int> &a, vector<int> &b) {\n            return a[0] > b[0]; \n        };\n        sort(edges.begin(), edges.end(), lambda);\n\n        int edge = 0;\n        for(auto &ed: edges) {\n            int type = ed[0];\n            int u = ed[1];\n            int v = ed[2];\n\n            if(type == 3) {\n                bool edgeAdded = false;\n                if(Alice.findParent(u) != Alice.findParent(v)) {\n                    Alice.unionByRank(u,v);\n                    edgeAdded = true;\n                }\n                if(Bob.findParent(u) != Bob.findParent(v)) {\n                    Bob.unionByRank(u,v);\n                    edgeAdded = true;\n                } \n                if(edgeAdded == true) {\n                    edge++;\n                }  \n            } else if (type == 2) {\n                if(Bob.findParent(u) != Bob.findParent(v)) {\n                    Bob.unionByRank(u,v);\n                    edge++;\n                }\n                \n            } else {\n                if(Alice.findParent(u) != Alice.findParent(v)) {\n                    Alice.unionByRank(u,v);\n                    edge++;\n                }\n            }\n        }\n        if(Alice.isSingle() == true and Bob.isSingle() == true) {\n            return edges.size() - edge;\n        }\n        return -1;\n    }\n};\n```
['Graph', 'C++']