public static int GetMaxClusters(IEnumerable<int> numbers, int bits, int maxSpacing) { var distinctNumbers = numbers.Distinct().ToArray(); int clusterCount = distinctNumbers.Length; var numberToCluster = new Dictionary<int, int>(); for (int i = 0; i < clusterCount; i++) { numberToCluster.Add(distinctNumbers[i], i); } var unionFind = new UnionFind(clusterCount); for (int spacing = 1; spacing <= maxSpacing; spacing++) { foreach (var number in distinctNumbers) { var modifications = GetModifications(number, bits, spacing, 0).ToArray(); foreach (var modification in modifications.Where(numberToCluster.ContainsKey)) { var cluster1 = unionFind.Find(numberToCluster[number]); var cluster2 = unionFind.Find(numberToCluster[modification]); if (cluster1 != cluster2) { unionFind.Union(cluster1, cluster2); clusterCount--; } } } } return clusterCount; }
public void UnionTest() { int n = 8; var unionFind = new UnionFind(n); for (int i = 0; i < n; i++) { unionFind.Find(i).Should().Be(i); } unionFind.Union(0, 1); var group1 = unionFind.Find(0); unionFind.Find(1).Should().Be(group1); unionFind.Union(2, 3); var group2 = unionFind.Find(2); unionFind.Find(3).Should().Be(group2); unionFind.Union(group1, group2); var groups = new int[] { unionFind.Find(0), unionFind.Find(1), unionFind.Find(2), unionFind.Find(3) }; groups.Distinct().Should().HaveCount(1); unionFind.Union(5, 6); var largeGroup = unionFind.Find(0); var smallGroup = unionFind.Find(5); unionFind.Union(largeGroup, smallGroup); unionFind.Find(5).Should().Be(largeGroup); unionFind.Find(6).Should().Be(largeGroup); }
public static int GetMaxSpacing(DirectedWeightedGraph graph, int clusterCount) { int currentClusterCount = graph.NodesCount; var unionFind = new UnionFind(currentClusterCount); var edges = new PriorityQueue<WeightedEdge, int>(graph.GetEdges().Select(e => new KeyValuePair<WeightedEdge, int>(e, e.Weight))); while (currentClusterCount >= clusterCount) { var edge = edges.ExtractHighestPriorityElement(); var cluster1 = unionFind.Find(edge.StartNode); var cluster2 = unionFind.Find(edge.EndNode); if (cluster1 != cluster2) { if (currentClusterCount == clusterCount) { return edge.Weight; } unionFind.Union(cluster1, cluster2); currentClusterCount--; } } return 0; }