84 lines
2.7 KiB
JavaScript
84 lines
2.7 KiB
JavaScript
// Interval graph coloring algorithm, by Twal
|
|
|
|
class IntervalColoration {
|
|
constructor (intervals) {
|
|
this.intervals = intervals;
|
|
this.n = this.intervals.length;
|
|
this.computeInterferenceGraph();
|
|
this.computePEO();
|
|
this.computeColoration();
|
|
}
|
|
|
|
computeInterferenceGraph() {
|
|
this.adj = new Array(this.n);
|
|
for (let i = 0; i < this.n; ++i) {
|
|
this.adj[i] = [];
|
|
}
|
|
for (let i = 0; i < this.n; ++i) {
|
|
for (let j = 0; j < i; ++j) {
|
|
let inti = this.intervals[i];
|
|
let intj = this.intervals[j];
|
|
if (inti[0] < intj[1] && intj[0] < inti[1]) {
|
|
this.adj[i].push(j);
|
|
this.adj[j].push(i);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//Perfect elimination order using Maximum Cardinality Search
|
|
//Runs in O(n^2), could be optimized in O(n log n)
|
|
computePEO() {
|
|
let marked = new Array(this.n);
|
|
let nbMarkedNeighbor = new Array(this.n);
|
|
this.perm = new Array(this.n);
|
|
for (let i = 0; i < this.n; ++i) {
|
|
marked[i] = false;
|
|
nbMarkedNeighbor[i] = 0;
|
|
}
|
|
for (let k = this.n-1; k >= 0; --k) {
|
|
let maxi = -1;
|
|
for (let i = 0; i < this.n; ++i) {
|
|
if (!marked[i] && (maxi == -1 || nbMarkedNeighbor[i] >= nbMarkedNeighbor[maxi])) {
|
|
maxi = i;
|
|
}
|
|
}
|
|
for (let i = 0; i < this.adj[maxi].length; ++i) {
|
|
nbMarkedNeighbor[this.adj[maxi][i]] += 1;
|
|
}
|
|
this.perm[maxi] = k;
|
|
marked[maxi] = true;
|
|
}
|
|
// console.log(this.perm);
|
|
}
|
|
|
|
computeColoration() {
|
|
this.colors = new Array(this.n);
|
|
let isColorUsed = new Array(this.n);
|
|
for (let i = 0; i < this.n; ++i) {
|
|
this.colors[i] = -1;
|
|
isColorUsed[i] = false;
|
|
}
|
|
for (let i = 0; i < this.n; ++i) {
|
|
let ind = this.perm[i];
|
|
for (let j = 0; j < this.adj[ind].length; ++j) {
|
|
let neigh = this.adj[ind][j];
|
|
if (this.colors[neigh] >= 0) {
|
|
isColorUsed[this.colors[neigh]] = true;
|
|
}
|
|
}
|
|
for (let j = 0; j < this.n; ++j) {
|
|
if (!isColorUsed[j]) {
|
|
this.colors[ind] = j;
|
|
break;
|
|
}
|
|
}
|
|
for (let j = 0; j < this.adj[ind].length; ++j) {
|
|
let neigh = this.adj[ind][j];
|
|
if (this.colors[neigh] >= 0) {
|
|
isColorUsed[this.colors[neigh]] = false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|