// Copyright (c) 2012, scribeGriff (Richard Griffith) // https://github.com/scribeGriff/graphlab // All rights reserved. Please see the LICENSE.md file. // // Converted to modern Dart by Pyrex Panjakar. /// A disjoint sets ADT implemented with a Union-Find data structure. /// /// Performs union-by-rank and path compression. Elements are represented /// by ints, numbered from zero. /// /// Each disjoint set has one element designated as its root. /// Negative values indicate the element is the root of a set. The absolute /// value of a negative value is the number of elements in the set. /// Positive values are an index to where the root was last known to be. /// If the set has been unioned with another, the last known root will point /// to a more recent root. /// /// var a = new UnionFind(myGraph.length); /// /// var u = a.find(myGraph[i][0]); /// var v = a.find(myGraph[i][1]); /// a.union(u, v); /// /// Reference: Direct port of Mark Allen Weiss' UnionFind.java class UnionFind { late final List array; /// Construct a disjoint sets object. /// /// numElements is the initial number of elements--also the initial /// number of disjoint sets, since every element is initially in its /// own set. UnionFind(int numElements) { // The array is zero based but the vertices are 1 based, // so we extend the array by 1 element to account for this. array = [for (var i = 0; i < numElements; i++) -1]; } /// union() unites two disjoint sets into a single set. A union-by-rank /// heuristic is used to choose the new root. /// /// a is an element in the first set. /// b is an element in the first set. void union(int a, int b) { int rootA = find(a); int rootB = find(b); if (rootA == rootB) return; if (array[rootB] < array[rootA]) { // root_b has more elements, so leave it as the root. // first, indicate that the set represented by root_b has grown. array[rootB] += array[rootA]; // Then, point the root of set a at set b. array[rootA] = rootB; } else { array[rootA] += array[rootB]; array[rootB] = rootA; } } /// find() finds the (int) name of the set containing a given element. /// Performs path compression along the way. /// /// x is the element sought. /// returns the set containing x. int find(int x) { if (array[x] < 0) { return x; // x is the root of the tree; return it } else { // Find out who the root is; compress path by making the root // x's parent. array[x] = find(array[x]); return array[x]; // Return the root } } }