C# Union-Find O(n) concise code
\npublic class Solution\n{\n    public int MaxNumEdgesToRemove(int n, int[][] edges)\n    {\n        int res = 0;\n        UnionFind alice = new UnionFind(n);\n
```\npublic class Solution\n{\n    public int MaxNumEdgesToRemove(int n, int[][] edges)\n    {\n        int res = 0;\n        UnionFind alice = new UnionFind(n);\n        UnionFind bob = new UnionFind(n);\n        foreach (var edge in edges)\n        {\n            if(edge[0] == 3 && (!alice.Union(edge[1], edge[2]) || !bob.Union(edge[1], edge[2])))\n                res++;\n        }\n\n        foreach (var edge in edges)\n        {\n            if (edge[0] == 1 && !alice.Union(edge[1], edge[2]))\n                res++;\n            if (edge[0] == 2 && !bob.Union(edge[1], edge[2]))\n                res++;\n        }\n\n        return alice.Componets == 1 && bob.Componets == 1 ? res : -1;\n    }\n}\n\npublic class UnionFind\n{\n    private int[] parent;\n    public int Componets { get; private set; }\n    public UnionFind(int n)\n    {\n        Componets = n;\n        parent = new int[n + 1];\n        for (int i = 0; i <= n; i++)\n        {\n            parent[i] = i;\n        }\n    }\n\n    public int Find(int x)\n    {\n        if (parent[x] != x)\n            parent[x] = Find(parent[x]);\n        return parent[x];\n    }\n\n    public bool Union(int x, int y)\n    {\n        int px = Find(x);\n        int py = Find(y);\n        if (px != py)\n        {\n            parent[px] = py;\n            Componets--;\n            return true;\n        }\n        return false;\n    }\n}\n```
[]