3
* @param {number[][]} edges6
var findCriticalAndPseudoCriticalEdges = function (n, edges) {7
// find and union utils8
const find = (x, parent) => {9
if (parent[x] === -1) {12
const y = find(parent[x], parent);16
const union = (a, b, parent) => {26
// sort and group edges by cost28
edges.forEach(([a, b, cost], i) => {29
map[cost] = map[cost] || [];30
map[cost].push([a, b, i]);32
const costs = Object.keys(map).sort((a, b) => a - b);35
const check = (edges, parent) => {39
// travel with a skipped point40
// if skip === -1, skip nothing and update count and nextParent.41
const travel = (skip) => {42
const p = [...parent];44
edges.forEach(([a, b, i]) => {53
count = result.length;59
// get default count and nextParent.62
// special case: there is only one edge in this group63
if (edges.length === 1) {65
return [[], [], 0, parent];67
return [[edges[0][2]], [], 1, nextParent];70
// aList -> critical, bList -> pseudo73
edges.forEach(([a, b, i]) => {74
if (find(a, parent) === find(b, parent)) {77
const result = travel(i);78
result.length < count ? (aList[i] = true) : (bList[i] = true);80
return [Object.keys(aList), Object.keys(bList), count, nextParent];83
// init traversal state87
let parent = new Array(n).fill(-1);89
// travel by cost group until all points visited90
for (let i = 0; i < costs.length; i++) {91
const [aList, bList, newCount, nextParent] = check(map[costs[i]], parent);92
critical.push(...aList);93
pseudo.push(...bList);96
if (count === n - 1) {101
return [critical, pseudo];