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