disjoint_sets.h 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. #pragma once
  2. #include <util/system/yassert.h>
  3. #include <util/generic/vector.h>
  4. // Implementation of disjoint-set data structure with union by rank and path compression.
  5. // See http://en.wikipedia.org/wiki/Disjoint-set_data_structure
  6. class TDisjointSets {
  7. public:
  8. using TElement = size_t;
  9. private:
  10. mutable TVector<TElement> Parents;
  11. TVector<size_t> Ranks;
  12. TVector<size_t> Sizes;
  13. size_t NumberOfSets;
  14. public:
  15. TDisjointSets(size_t setCount)
  16. : Parents(setCount)
  17. , Ranks(setCount, 0)
  18. , Sizes(setCount, 1)
  19. , NumberOfSets(setCount)
  20. {
  21. for (size_t i = 0; i < setCount; ++i)
  22. Parents[i] = i;
  23. }
  24. TElement CanonicSetElement(TElement item) const {
  25. if (Parents[item] != item)
  26. Parents[item] = CanonicSetElement(Parents[item]);
  27. return Parents[item];
  28. }
  29. size_t SizeOfSet(TElement item) const {
  30. return Sizes[CanonicSetElement(item)];
  31. }
  32. size_t InitialSetCount() const {
  33. return Parents.size();
  34. }
  35. size_t SetCount() const {
  36. return NumberOfSets;
  37. }
  38. void UnionSets(TElement item1, TElement item2) {
  39. TElement canonic1 = CanonicSetElement(item1);
  40. TElement canonic2 = CanonicSetElement(item2);
  41. if (canonic1 == canonic2)
  42. return;
  43. --NumberOfSets;
  44. if (Ranks[canonic1] < Ranks[canonic2]) {
  45. Parents[canonic1] = canonic2;
  46. Sizes[canonic2] += Sizes[canonic1];
  47. } else {
  48. Parents[canonic2] = canonic1;
  49. Sizes[canonic1] += Sizes[canonic2];
  50. Ranks[canonic2] += Ranks[canonic1] == Ranks[canonic2] ? 1 : 0;
  51. }
  52. }
  53. void Expand(size_t setCount) {
  54. if (setCount < Parents.size()) {
  55. return;
  56. }
  57. size_t prevSize = Parents.size();
  58. Parents.resize(setCount);
  59. Ranks.resize(setCount);
  60. Sizes.resize(setCount);
  61. NumberOfSets += setCount - prevSize;
  62. for (size_t i = prevSize; i < setCount; ++i) {
  63. Parents[i] = i;
  64. Ranks[i] = 0;
  65. Sizes[i] = 1;
  66. }
  67. }
  68. };