|
| 1 | +/** |
| 2 | + * 1579. Remove Max Number of Edges to Keep Graph Fully Traversable |
| 3 | + * https://leetcode.com/problems/remove-max-number-of-edges-to-keep-graph-fully-traversable/ |
| 4 | + * Difficulty: Hard |
| 5 | + * |
| 6 | + * Alice and Bob have an undirected graph of n nodes and three types of edges: |
| 7 | + * - Type 1: Can be traversed by Alice only. |
| 8 | + * - Type 2: Can be traversed by Bob only. |
| 9 | + * - Type 3: Can be traversed by both Alice and Bob. |
| 10 | + * |
| 11 | + * Given an array edges where edges[i] = [typei, ui, vi] represents a bidirectional edge of type |
| 12 | + * typei between nodes ui and vi, find the maximum number of edges you can remove so that after |
| 13 | + * removing the edges, the graph can still be fully traversed by both Alice and Bob. The graph |
| 14 | + * is fully traversed by Alice and Bob if starting from any node, they can reach all other nodes. |
| 15 | + * |
| 16 | + * Return the maximum number of edges you can remove, or return -1 if Alice and Bob cannot fully |
| 17 | + * traverse the graph. |
| 18 | + */ |
| 19 | + |
| 20 | +/** |
| 21 | + * @param {number} n |
| 22 | + * @param {number[][]} edges |
| 23 | + * @return {number} |
| 24 | + */ |
| 25 | +var maxNumEdgesToRemove = function(n, edges) { |
| 26 | + const alice = new UnionFind(n + 1); |
| 27 | + const bob = new UnionFind(n + 1); |
| 28 | + let removableEdges = 0; |
| 29 | + |
| 30 | + for (const [type, u, v] of edges) { |
| 31 | + if (type === 3) { |
| 32 | + const usedAlice = alice.union(u, v); |
| 33 | + const usedBob = bob.union(u, v); |
| 34 | + if (!usedAlice && !usedBob) { |
| 35 | + removableEdges++; |
| 36 | + } |
| 37 | + } |
| 38 | + } |
| 39 | + |
| 40 | + for (const [type, u, v] of edges) { |
| 41 | + if (type === 1) { |
| 42 | + if (!alice.union(u, v)) { |
| 43 | + removableEdges++; |
| 44 | + } |
| 45 | + } else if (type === 2) { |
| 46 | + if (!bob.union(u, v)) { |
| 47 | + removableEdges++; |
| 48 | + } |
| 49 | + } |
| 50 | + } |
| 51 | + |
| 52 | + return alice.components === 2 && bob.components === 2 ? removableEdges : -1; |
| 53 | +}; |
| 54 | + |
| 55 | +class UnionFind { |
| 56 | + constructor(size) { |
| 57 | + this.parent = Array(size).fill().map((_, i) => i); |
| 58 | + this.rank = Array(size).fill(0); |
| 59 | + this.components = size; |
| 60 | + } |
| 61 | + |
| 62 | + find(x) { |
| 63 | + if (this.parent[x] !== x) { |
| 64 | + this.parent[x] = this.find(this.parent[x]); |
| 65 | + } |
| 66 | + return this.parent[x]; |
| 67 | + } |
| 68 | + |
| 69 | + union(x, y) { |
| 70 | + const rootX = this.find(x); |
| 71 | + const rootY = this.find(y); |
| 72 | + if (rootX === rootY) return false; |
| 73 | + if (this.rank[rootX] < this.rank[rootY]) { |
| 74 | + this.parent[rootX] = rootY; |
| 75 | + } else if (this.rank[rootX] > this.rank[rootY]) { |
| 76 | + this.parent[rootY] = rootX; |
| 77 | + } else { |
| 78 | + this.parent[rootY] = rootX; |
| 79 | + this.rank[rootX]++; |
| 80 | + } |
| 81 | + this.components--; |
| 82 | + return true; |
| 83 | + } |
| 84 | +} |
0 commit comments