Swift UnionFind
\n# Code\n\nclass Solution {\n    \n    enum UnType: Int {\n        case alice = 1\n        case bob = 2\n        case both = 3\n    }\n\n    func maxNumEdgesTo
\n# Code\n```\nclass Solution {\n    \n    enum UnType: Int {\n        case alice = 1\n        case bob = 2\n        case both = 3\n    }\n\n    func maxNumEdgesToRemove(_ n: Int, _ edges: [[Int]]) -> Int {\n        \n        var edges = edges.map { (type: UnType(rawValue: $0[0])!, from: $0[1], to: $0[2]) }.sorted { $0.type.rawValue > $1.type.rawValue }\n        var unionA = Union(n)\n        var unionB = Union(n)\n        \n        var extra = 0\n        for edge in edges {\n            \n            switch edge.type {\n            case .both:\n                let aConnected = unionA.wasConnected(edge.from, edge.to)\n                let bConnected = unionB.wasConnected(edge.from, edge.to)\n                if aConnected && bConnected { extra += 1 }\n            case .alice:\n                if unionA.wasConnected(edge.from, edge.to) { extra += 1 }\n            case .bob:\n                if unionB.wasConnected(edge.from, edge.to) { extra += 1 }\n            }\n        }\n        \n        return unionB.connected() && unionA.connected() ? extra : -1\n    }\n}\n\nclass Union {\n    \n    private var union: [Int]\n    private var ranks: [Int]\n    \n    init(_ n: Int) {\n        union = Array(repeating: 0, count: n + 1).enumerated().map { $0.offset }\n        ranks = Array(repeating: 1, count: n + 1)\n    }\n    \n    // return true if i and j was connected previously\n    func wasConnected(_ i: Int, _ j: Int) -> Bool {\n        if areConnected(i, j) { return true }\n        union(i, j)\n        return false\n    }\n    \n    func root(of node: Int) -> Int {\n        var node = node\n        while node != union[node] {\n            node = union[node]\n        }\n        return node\n    }\n    \n    func areConnected(_ i: Int, _ j: Int) -> Bool {\n        root(of: i) == root(of: j)\n    }\n    \n    func union(_ i: Int, _ j: Int) {\n        if i == j { return }\n        let iRoot = root(of: i)\n        let jRoot = root(of: j)\n        if iRoot == jRoot { return }\n        \n        if ranks[iRoot] < ranks[jRoot] {\n            union[iRoot] = jRoot\n            ranks[jRoot] += ranks[iRoot]\n        } else {\n            union[jRoot] = iRoot\n            ranks[iRoot] += ranks[jRoot]\n        }\n    }\n    \n    func connected() -> Bool {\n        Set(union.suffix(from: 1).map { root(of: $0) }).count == 1\n    }\n}\n```
['Swift']