-
Notifications
You must be signed in to change notification settings - Fork 119
/
Copy pathLongest Cycle in a Graph.js
96 lines (90 loc) · 2.81 KB
/
Longest Cycle in a Graph.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
85
86
87
88
89
90
91
92
93
94
95
// Runtime: 4875 ms (Top 5.9%) | Memory: 114.72 MB (Top 34.5%)
/**
* @param {number[]} edges
* @return {number}
*/
function getCycleTopology(edges){
const indeg = new Array(edges.length).fill(0);
const queue = [];
const map = {};
for(const src in edges){
const des = edges[src]
if(des >= 0){
indeg[des] ++;
}
map[src] ? map[src].push(des) : map[src] = [des]
}
for(const node in indeg){
if(indeg[node] === 0){
queue.push(node)
}
}
while(queue.length > 0){
const node = queue.shift();
for(const connectedNode of map[node]){
if(connectedNode !== -1){
indeg[connectedNode] --;
if(indeg[connectedNode] === 0){
queue.push(connectedNode);
}
}
}
}
return indeg
}
class DisjointSet{
constructor(n){
this.n = n;
this.root = new Array(n).fill(0).map((_,i) => i);
this.rank = new Array(n).fill(1);
}
find(x){
if(x === this.root[x]) return x;
return this.root[x] = this.find(this.root[x]);
}
union(x,y){
const x_root = this.find(x);
const y_root = this.find(y);
if(this.rank[x_root] < this.rank[y_root]){
[this.rank[x_root] , this.rank[y_root]] = [this.rank[y_root] , this.rank[x_root]];
}
this.root[y_root] = x_root;
if(this.rank[x_root] === this.rank[y_root]) this.rank[x_root] ++;
}
_getGroupsComponentCounts(){
let groups = {};
for(const node of this.root){
const node_root = this.find(node);
groups[node_root] = groups[node_root] +1 || 1
}
return groups
}
getLongestGroupComponentLength(){
let longestLength = 1;
const lengths = this._getGroupsComponentCounts();
for(const length of Object.values(lengths)){
if(length > 1){
longestLength = Math.max(longestLength, length);
}
}
return longestLength > 1 ? longestLength : -1;
}
}
var longestCycle = function(edges) {
const djs = new DisjointSet(edges.length);
let res = -1
// topology sort results topology array.
// component with greater than 0 is cyclic component.
// now we need to get groups of cycle since we can't distinguish each cycles with current datas.
const cycleComponent = getCycleTopology(edges);
//with edges info and cycle component data, we can now distinguish each cycle group by union finde
// because each cycle r independent with each other.
for(const src in edges){
const des = edges[src];
if(cycleComponent[src] && cycleComponent[des]){
djs.union(src, des);
}
}
res = djs.getLongestGroupComponentLength()
return res
};