Go HARD 62%
\n\n# Code\n\ntype UnionFind struct {\n    representative []int\n    componentSize []int\n    components int\n}\n\nfunc New(n int) *UnionFind {\n    uf := Union
\n\n# Code\n```\ntype UnionFind struct {\n    representative []int\n    componentSize []int\n    components int\n}\n\nfunc New(n int) *UnionFind {\n    uf := UnionFind{}\n    uf.components = n\n    uf.representative = make([]int, n+1)\n    uf.componentSize = make([]int, n+1)\n    for i := range uf.representative {\n        uf.representative[i] = i\n        uf.componentSize[i] = 1\n    }\n    return &uf\n}\n\nfunc (uf *UnionFind) findRepresentative(x int) int {\n    if uf.representative[x] == x {\n        return x\n    }\n    uf.representative[x] = uf.findRepresentative(uf.representative[x])\n    return uf.representative[x]\n}\n\nfunc (uf *UnionFind) performUnion(x int, y int) int {\n    x, y = uf.findRepresentative(x), uf.findRepresentative(y)\n\n    if x == y {\n        return 0\n    }\n    if uf.componentSize[x] > uf.componentSize[y] {\n        uf.representative[y] = x\n        uf.componentSize[x] += uf.componentSize[y]\n    } else {\n        uf.representative[x] = y\n        uf.componentSize[y] += uf.componentSize[x]\n    }\n    uf.components--\n    return 1\n}\n\nfunc (uf *UnionFind) isConnected() bool {\n    return uf.components == 1\n}\n\nfunc maxNumEdgesToRemove(n int, edges [][]int) int {\n    Alice, Bob := New(n), New(n)\n    edgesRequired := 0\n    for _, edge := range edges {\n        if edge[0] == 3 {\n            edgesRequired += Alice.performUnion(edge[1], edge[2]) | Bob.performUnion(edge[1], edge[2])\n        }\n    }\n\n    for _, edge := range edges {\n        if edge[0] == 1 {\n            edgesRequired += Alice.performUnion(edge[1], edge[2])\n        } else if edge[0] == 2 {\n            edgesRequired += Bob.performUnion(edge[1], edge[2])\n        }\n    }\n\n    if Alice.isConnected() && Bob.isConnected() {\n        return len(edges) - edgesRequired\n    }\n\n    return -1\n}\n```
['Go']