Swift | Union Find | Smallest & Fastest solution
Union Find (accepted answer)\n\nclass Solution {\n    func maxNumEdgesToRemove(_ n: Int, _ edges: [[Int]]) -> Int {\n        var groups = [Array(0...n), Array(0
**Union Find (accepted answer)**\n```\nclass Solution {\n    func maxNumEdgesToRemove(_ n: Int, _ edges: [[Int]]) -> Int {\n        var groups = [Array(0...n), Array(0...n)] // [0] = alice, [1] = bob\n        var connectedCounts = [0,0], edgesNeeded = 0\n\n        func find(_ x: Int, _ group: inout [Int]) -> Int {\n            if x != group[x] { group[x] = find(group[x], &group) }\n            return group[x]\n        }\n\n        func tryUnion(_ i:Int, _ j:Int, _ g:Int) -> Bool {\n            let (x,y) = (find(i, &groups[g]), find(j, &groups[g]))\n            groups[g][x] = y\n            connectedCounts[g] += x != y ? 1 : 0\n            return x != y\n        }\n\n        let ALICE = 1, BOB = 2, ALICE_OR_BOB = 3\n\n        for e in edges where e[0] == ALICE_OR_BOB && tryUnion(e[1], e[2], 0) && tryUnion(e[1], e[2], 1) {\n            edgesNeeded += 1  // Connect edges that both can use\n        }\n\n        for e in edges where (e[0] == ALICE && tryUnion(e[1], e[2], 0)) || (e[0] == BOB && tryUnion(e[1], e[2], 1)) {\n            edgesNeeded += 1  // Connect edges that are not already joined for both\n        }\n        \n        return connectedCounts.allSatisfy { $0 == n-1 } ? edges.count - edgesNeeded : -1\n    }\n}\n```
['Swift']