-
Notifications
You must be signed in to change notification settings - Fork 2.5k
Expand file tree
/
Copy path1489-find-critical-and-pseudo-critical-edges-in-minimum-spanning-tree.ts
More file actions
124 lines (103 loc) · 3.24 KB
/
1489-find-critical-and-pseudo-critical-edges-in-minimum-spanning-tree.ts
File metadata and controls
124 lines (103 loc) · 3.24 KB
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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
type Edge = [number, number, number];
class UnionFind {
parents: number[];
ranks: number[];
constructor(n: number) {
this.parents = Array.from({ length: n }, (_, i) => i);
this.ranks = Array.from({ length: n }, () => 0);
}
find(node: number) {
let current = this.parents[node];
while (current !== this.parents[current]) {
this.parents[current] = this.parents[this.parents[current]];
current = this.parents[current];
}
return current;
}
union(a: number, b: number) {
const pa = this.find(a);
const pb = this.find(b);
if (pa === pb) return false;
if (this.ranks[pa] > this.ranks[pb]) {
this.parents[pb] = pa;
} else if (this.ranks[pa] < this.ranks[pb]) {
this.parents[pa] = pb;
} else {
this.parents[pb] = pa;
this.ranks[pa]++;
}
return true;
}
}
function findMST(
n: number,
edges: Edge[],
heap: typeof MinPriorityQueue,
): { edges: Edge[]; sum: number } {
const unionFind = new UnionFind(n);
const resultingEdges = [];
let sum = 0;
if (!heap.isEmpty()) {
const { element: minEdge } = heap.dequeue();
unionFind.union(minEdge[0], minEdge[1]);
resultingEdges.push(minEdge);
sum += minEdge[2];
}
for (let edge of edges) {
heap.enqueue(edge);
}
while (!heap.isEmpty() && resultingEdges.length < n - 1) {
const { element: minEdge } = heap.dequeue();
const isUnion = unionFind.union(minEdge[0], minEdge[1]);
if (!isUnion) continue;
resultingEdges.push(minEdge);
sum += minEdge[2];
}
if (resultingEdges.length < n - 1) return { sum: Infinity, edges: [] };
return { edges: resultingEdges, sum };
}
function buildHeap() {
return new MinPriorityQueue({ priority: (edge) => edge[2] });
}
function findCriticalAndPseudoCriticalEdges(
n: number,
edges: Edge[],
): number[][] {
const generalMST = findMST(n, edges, buildHeap());
const criticalEdges = [];
for (let edgeToExclude of generalMST.edges) {
const newEdges = edges.filter(
(edge) => edge.join(',') !== edgeToExclude.join(','),
);
const mst = findMST(n, newEdges, buildHeap());
if (mst.sum > generalMST.sum) {
criticalEdges.push(edgeToExclude);
}
}
const pseudoCriticalEdges = [];
for (let edge of edges) {
if (criticalEdges.map((e) => e.join(',')).includes(edge.join(',')))
continue;
const newEdges = edges.filter(
(possibleEdge) => possibleEdge.join(',') !== edge.join(','),
);
const heap = buildHeap();
heap.enqueue(edge);
const mst = findMST(n, newEdges, heap);
if (mst.sum === generalMST.sum) {
pseudoCriticalEdges.push(edge);
}
}
return [
criticalEdges.map((criticalEdge) =>
edges.findIndex(
(edge) => edge.join(',') === criticalEdge.join(','),
),
),
pseudoCriticalEdges.map((pCriticalEdge) =>
edges.findIndex(
(edge) => edge.join(',') === pCriticalEdge.join(','),
),
),
];
}