用于存放学校的作业便于复习。
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

235 lines
6.3 KiB

  1. //
  2. // Created by 423A35C7 on 2023-12-02.
  3. //
  4. #ifndef GRAPH_H
  5. #define GRAPH_H
  6. #include <algorithm>
  7. #include <iostream>
  8. #include <memory>
  9. #include <random>
  10. #include <cstring>
  11. #include <list>
  12. #include <map>
  13. std::default_random_engine engine(time(nullptr));
  14. class MergeFindSet {
  15. using int_ptr = std::unique_ptr<int>;
  16. public:
  17. const int length;
  18. explicit MergeFindSet(const int n)
  19. : length(n), elements(new int[n]) {
  20. memset(this->elements.get(), -1, n * sizeof(int));
  21. }
  22. int find(const int index) {
  23. return elements.get()[index] == -1
  24. ? index
  25. : elements.get()[index] = find(elements.get()[index]);
  26. }
  27. void merge(const int a, const int b) {
  28. elements.get()[find(b)] = find(a);
  29. }
  30. friend std::ostream& operator<<(std::ostream&out, const MergeFindSet&merge_find_set);
  31. private:
  32. int_ptr elements;
  33. };
  34. std::ostream& operator<<(std::ostream&out, const MergeFindSet&merge_find_set) {
  35. for (int i = 0; i < merge_find_set.length; ++i) {
  36. out << merge_find_set.elements.get()[i] << "\t";
  37. }
  38. return out;
  39. }
  40. /**
  41. * \brief
  42. * \tparam T
  43. * \param high_dimension int**, bool***
  44. * \param length
  45. * \param dimensino_num
  46. */
  47. template<typename T>
  48. void print(void* high_dimension, const int length, const int dimensino_num = 1) {
  49. void** temp = static_cast<void **>(high_dimension);
  50. if (dimensino_num <= 1) {
  51. for (int i = 0; i < length; ++i) {
  52. std::cout << static_cast<T *>(high_dimension)[i] << "\t";
  53. }
  54. std::cout << std::endl;
  55. return;
  56. }
  57. for (int i = 0; i < length; ++i) {
  58. print<T>(temp[i], length, dimensino_num - 1);
  59. }
  60. std::cout << std::endl;
  61. }
  62. class Graph {
  63. public:
  64. ~Graph() {
  65. for (int i = 0; i < this->node_num; ++i) {
  66. delete this->adjacency[i];
  67. }
  68. delete this->adjacency;
  69. for (int i = 0; i < this->node_num; ++i) {
  70. delete this->incidence[i];
  71. }
  72. delete this->incidence;
  73. }
  74. explicit Graph(const int n)
  75. : merge_find_set_(n) {
  76. this->node_num = n;
  77. std::uniform_int_distribution<int> get_random(1, 100);
  78. this->adjacency = new int *[n];
  79. this->incidence = new bool *[n];
  80. for (int i = 0; i < n; ++i) {
  81. this->adjacency[i] = new int[n];
  82. this->incidence[i] = new bool[n];
  83. memset(this->incidence[i], 0, n * sizeof(bool));
  84. this->adjacency[i][i] = INT_MAX;
  85. for (int j = 0; j < i; ++j) {
  86. this->adjacency[i][j] = this->adjacency[j][i] = get_random(engine);
  87. }
  88. }
  89. }
  90. void print_adjacency() const {
  91. print<int>(this->adjacency, this->node_num, 2);
  92. }
  93. void print_incidence() const {
  94. print<bool>(this->incidence, this->node_num, 2);
  95. }
  96. void print_merge_find_set() {
  97. std::cout << this->merge_find_set_ << std::endl;
  98. }
  99. bool same_league(const int start, const int target) {
  100. return this->merge_find_set_.find(start) == this->merge_find_set_.find(target);
  101. }
  102. /**
  103. * \brief
  104. * \param start
  105. * \param target
  106. */
  107. void merge(const int start, const int target) {
  108. this->merge_find_set_.merge(start, target);
  109. }
  110. /**
  111. * \brief
  112. */
  113. void start_record_incidence() {
  114. this->incidence_had_changed = false;
  115. }
  116. /**
  117. * \brief
  118. * \return
  119. */
  120. bool stop_record_incidence() {
  121. const bool temp = this->incidence_had_changed;
  122. this->incidence_had_changed = false;
  123. return temp;
  124. }
  125. friend void one_turn(Graph*);
  126. protected:
  127. /**
  128. * \brief
  129. */
  130. int** adjacency; // 邻接矩阵
  131. /**
  132. * \brief
  133. */
  134. int node_num;
  135. /**
  136. * \brief true
  137. */
  138. bool** incidence; // 关系矩阵
  139. bool incidence_had_changed;
  140. MergeFindSet merge_find_set_;
  141. };
  142. class ComplexGraph : public Graph {
  143. public:
  144. ~ComplexGraph() {
  145. // this->~Graph(); // 好像析构函数会自动调用,不需要手动调用
  146. delete this->alpha;
  147. }
  148. explicit ComplexGraph(const int n)
  149. : Graph(n) {
  150. this->alpha = new int[n];
  151. std::uniform_int_distribution<int> get_random(1, n / 2);
  152. for (int i = 0; i < n; ++i) {
  153. this->alpha[i] = get_random(engine);
  154. }
  155. }
  156. void print_alpha() {
  157. // print<int>(this->alpha, this->node_num, 1);
  158. std::map<int, std::list<int>> index_to_league;
  159. for (int i = 0; i < this->node_num; ++i) {
  160. int ancestor = this->merge_find_set_.find(i);
  161. if (!index_to_league.contains(ancestor)) {
  162. index_to_league.insert({ancestor, {}});
  163. }
  164. index_to_league[ancestor].push_back(i);
  165. }
  166. for (const auto&[ancestor, child]: index_to_league) {
  167. std::cout << "城市联盟 { ";
  168. for (auto value: child) {
  169. std::cout << value << " ";
  170. }
  171. std::cout << " } 的规模系数为 ";
  172. std::cout << this->get_alpha(ancestor) << std::endl;
  173. }
  174. }
  175. void set_beta(const int beta) {
  176. this->beta = beta;
  177. }
  178. /**
  179. * \brief
  180. * \param index
  181. * \return
  182. */
  183. [[nodiscard]] int get_alpha(const int index) {
  184. return this->alpha[this->merge_find_set_.find(index)];
  185. }
  186. /**
  187. * \brief 1
  188. * \param index
  189. */
  190. void increase_alpha(const int index) {
  191. this->alpha[this->merge_find_set_.find(index)]++;
  192. }
  193. friend void one_turn(ComplexGraph*);
  194. private:
  195. /**
  196. * \brief
  197. */
  198. int* alpha;
  199. int beta = 0; // 限定系数
  200. };
  201. #endif //GRAPH_H