236 lines
6.3 KiB
C++
236 lines
6.3 KiB
C++
|
//
|
|||
|
// Created by 423A35C7 on 2023-12-02.
|
|||
|
//
|
|||
|
|
|||
|
#ifndef GRAPH_H
|
|||
|
#define GRAPH_H
|
|||
|
|
|||
|
#include <algorithm>
|
|||
|
#include <iostream>
|
|||
|
#include <memory>
|
|||
|
#include <random>
|
|||
|
#include <cstring>
|
|||
|
#include <list>
|
|||
|
#include <map>
|
|||
|
|
|||
|
std::default_random_engine engine(time(nullptr));
|
|||
|
|
|||
|
class MergeFindSet {
|
|||
|
using int_ptr = std::unique_ptr<int>;
|
|||
|
|
|||
|
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<typename T>
|
|||
|
void print(void* high_dimension, const int length, const int dimensino_num = 1) {
|
|||
|
void** temp = static_cast<void **>(high_dimension);
|
|||
|
if (dimensino_num <= 1) {
|
|||
|
for (int i = 0; i < length; ++i) {
|
|||
|
std::cout << static_cast<T *>(high_dimension)[i] << "\t";
|
|||
|
}
|
|||
|
std::cout << std::endl;
|
|||
|
return;
|
|||
|
}
|
|||
|
for (int i = 0; i < length; ++i) {
|
|||
|
print<T>(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<int> 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<int>(this->adjacency, this->node_num, 2);
|
|||
|
}
|
|||
|
|
|||
|
void print_incidence() const {
|
|||
|
print<bool>(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<int> get_random(1, n / 2);
|
|||
|
for (int i = 0; i < n; ++i) {
|
|||
|
this->alpha[i] = get_random(engine);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void print_alpha() {
|
|||
|
// print<int>(this->alpha, this->node_num, 1);
|
|||
|
std::map<int, std::list<int>> 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
|