-
Notifications
You must be signed in to change notification settings - Fork 229
/
Copy path1489-find-critical-and-pseudo-critical-edges-in-minimum-spanning-tree.js
69 lines (69 loc) · 1.74 KB
/
1489-find-critical-and-pseudo-critical-edges-in-minimum-spanning-tree.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
/**
* @param {number} n
* @param {number[][]} edges
* @return {number[][]}
*/
const findCriticalAndPseudoCriticalEdges = function (n, edges) {
const criticalEdges = [],
psuedoCriticalEdges = [],
map = new Map()
edges.forEach((edge, i) => map.set(edge, i))
edges.sort((a, b) => a[2] - b[2])
const buildMST = (pick, skip) => {
const uf = new UnionFind(n)
let cost = 0
if (pick !== null) {
uf.union(pick[0], pick[1])
cost += pick[2]
}
for (let edge of edges) {
if (edge !== skip && uf.union(edge[0], edge[1])) cost += edge[2]
}
return uf.count === 1 ? cost : Number.MAX_SAFE_INTEGER
}
const minCost = buildMST(null, null)
for (let edge of edges) {
const index = map.get(edge)
const costWithout = buildMST(null, edge)
if (costWithout > minCost) {
criticalEdges.push(index)
} else {
const costWith = buildMST(edge, null)
if (costWith === minCost) psuedoCriticalEdges.push(index)
}
}
return [criticalEdges, psuedoCriticalEdges]
}
class UnionFind {
constructor(n) {
this.parents = Array(n)
.fill(0)
.map((e, i) => i)
this.ranks = Array(n).fill(0)
this.count = n
}
root(x) {
while (x !== this.parents[x]) {
this.parents[x] = this.parents[this.parents[x]]
x = this.parents[x]
}
return x
}
find(x) {
return this.root(x)
}
union(x, y) {
const [rx, ry] = [this.find(x), this.find(y)]
if (this.ranks[rx] >= this.ranks[ry]) {
this.parents[ry] = rx
this.ranks[rx] += this.ranks[ry]
} else if (this.ranks[ry] > this.ranks[rx]) {
this.parents[rx] = ry
this.ranks[ry] += this.ranks[rx]
}
if (rx !== ry) {
this.count--
return true
} else return false
}
}