// // Created by 423A35C7 on 2023-12-02. // #ifndef GRAPH_H #define GRAPH_H #include #include #include #include #include #include #include std::default_random_engine engine(time(nullptr)); class MergeFindSet { using int_ptr = std::unique_ptr; public: const int length; explicit MergeFindSet(const int n) : length(n), elements(new int[n]) { memset(this->elements.get(), -1, n * sizeof(int)); } int find(const int index) { return elements.get()[index] == -1 ? index : elements.get()[index] = find(elements.get()[index]); } void merge(const int a, const int b) { elements.get()[find(b)] = find(a); } friend std::ostream& operator<<(std::ostream&out, const MergeFindSet&merge_find_set); private: int_ptr elements; }; std::ostream& operator<<(std::ostream&out, const MergeFindSet&merge_find_set) { for (int i = 0; i < merge_find_set.length; ++i) { out << merge_find_set.elements.get()[i] << "\t"; } return out; } /** * \brief 打印高维类型 * \tparam T 最内层的类型 * \param high_dimension 高维指针,应为 int**, bool*** 等类似的类型 * \param length 长度(每一维的长度都应一样) * \param dimensino_num 维度 */ template void print(void* high_dimension, const int length, const int dimensino_num = 1) { void** temp = static_cast(high_dimension); if (dimensino_num <= 1) { for (int i = 0; i < length; ++i) { std::cout << static_cast(high_dimension)[i] << "\t"; } std::cout << std::endl; return; } for (int i = 0; i < length; ++i) { print(temp[i], length, dimensino_num - 1); } std::cout << std::endl; } class Graph { public: ~Graph() { for (int i = 0; i < this->node_num; ++i) { delete this->adjacency[i]; } delete this->adjacency; for (int i = 0; i < this->node_num; ++i) { delete this->incidence[i]; } delete this->incidence; } explicit Graph(const int n) : merge_find_set_(n) { this->node_num = n; std::uniform_int_distribution get_random(1, 100); this->adjacency = new int *[n]; this->incidence = new bool *[n]; for (int i = 0; i < n; ++i) { this->adjacency[i] = new int[n]; this->incidence[i] = new bool[n]; memset(this->incidence[i], 0, n * sizeof(bool)); this->adjacency[i][i] = INT_MAX; for (int j = 0; j < i; ++j) { this->adjacency[i][j] = this->adjacency[j][i] = get_random(engine); } } } void print_adjacency() const { print(this->adjacency, this->node_num, 2); } void print_incidence() const { print(this->incidence, this->node_num, 2); } void print_merge_find_set() { std::cout << this->merge_find_set_ << std::endl; } bool same_league(const int start, const int target) { return this->merge_find_set_.find(start) == this->merge_find_set_.find(target); } /** * \brief 把目标城市所在联盟合并到起始城市所在联盟中 * \param start 起始城市 * \param target 目标城市 */ void merge(const int start, const int target) { this->merge_find_set_.merge(start, target); } /** * \brief 开始记录关系矩阵是否被改变 */ void start_record_incidence() { this->incidence_had_changed = false; } /** * \brief 停止记录并返回关系矩阵是否被改变 * \return 关系矩阵是否被改变 */ bool stop_record_incidence() { const bool temp = this->incidence_had_changed; this->incidence_had_changed = false; return temp; } friend void one_turn(Graph*); protected: /** * \brief 邻接矩阵,表示任意两个城市之间的距离 */ int** adjacency; // 邻接矩阵 /** * \brief 城市数量 */ int node_num; /** * \brief 关系矩阵,任意两个城市之间如果有直接的公路则为true(是对称的,反自反的关系)(不一定满足传递性) */ bool** incidence; // 关系矩阵 bool incidence_had_changed; MergeFindSet merge_find_set_; }; class ComplexGraph : public Graph { public: ~ComplexGraph() { // this->~Graph(); // 好像析构函数会自动调用,不需要手动调用 delete this->alpha; } explicit ComplexGraph(const int n) : Graph(n) { this->alpha = new int[n]; std::uniform_int_distribution get_random(1, n / 2); for (int i = 0; i < n; ++i) { this->alpha[i] = get_random(engine); } } void print_alpha() { // print(this->alpha, this->node_num, 1); std::map> index_to_league; for (int i = 0; i < this->node_num; ++i) { int ancestor = this->merge_find_set_.find(i); if (!index_to_league.contains(ancestor)) { index_to_league.insert({ancestor, {}}); } index_to_league[ancestor].push_back(i); } for (const auto&[ancestor, child]: index_to_league) { std::cout << "城市联盟 { "; for (auto value: child) { std::cout << value << " "; } std::cout << " } 的规模系数为 "; std::cout << this->get_alpha(ancestor) << std::endl; } } void set_beta(const int beta) { this->beta = beta; } /** * \brief 获取城市所在联盟的规模系数 * \param index 城市序号 * \return 城市所在联盟的规模系数 */ [[nodiscard]] int get_alpha(const int index) { return this->alpha[this->merge_find_set_.find(index)]; } /** * \brief 城市所在联盟的规模系数增加1 * \param index 城市序号 */ void increase_alpha(const int index) { this->alpha[this->merge_find_set_.find(index)]++; } friend void one_turn(ComplexGraph*); private: /** * \brief 每个城市的规模系数 */ int* alpha; int beta = 0; // 限定系数 }; #endif //GRAPH_H