#include #include #include #include #include #include #include #include #include "edge.hpp" #define MAX 100 using namespace std; template class Graph { public: int wealth[MAX]; map>> adj; /* 邻接表 */ bool contains(const T& u); /* 判断顶点u是否在图中 */ bool adjacent(const T& u, const T& v); /* 判断顶点u和v是否相邻 */ void add_vertex(const T& u); /* 添加顶点 */ void add_edge(const T& u, const T& v, int weight); /* 添加边和权重 */ void change_weight(const T& u, const T& v, int weight); /* 修改权重 */ void remove_weight(const T& u, const T& v); /* 移除权重 */ void remove_vertex(const T& u); /* 移除顶点 */ void remove_edge(const T& u, const T& v); /* 移除边 */ int degree(const T& u); /* 求顶点的度数 */ int num_vertices(); /* 求图中顶点的总数 */ int num_edges(); /* 求图中边的总数*/ int largest_degree(); /* 求图中的最大度数 */ int get_weight(const T& u, const T& v); /* 得到某两个顶点之间边的权重 */ vector get_vertices(); /* 得到图中所有顶点 */ void show_neighbours(const T& u); /* 得到顶点u的所有边 */ string get_neighbours(const T& u); int get_wealth(const T u); void show(); void dft_recursion(const T& u, set& visited, vector& result); /* 深度优先遍历递归辅助函数 */ vector depth_first_rec(const T& u); /* 深度优先遍历递归法 */ vector depth_first_itr(const T& u); /* 深度优先遍历迭代法*/ vector breadth_first(const T& u); /* 广度优先遍历迭代法 */ string dijkstra(const T start); /* dijkstra最短路径算法 */ }; template void Graph::show() { int i = 0; for (const auto& u : adj) { cout << "城堡" << u.first << "(" << this->wealth[i] << "): "; for (const auto& v : adj[u.first]) cout << "[->城堡" << v.vertex << " 危险值: " << v.weight << "]"; cout << endl; i++; } } template bool Graph::contains(const T& u) { return adj.find(u) != adj.end(); } template bool Graph::adjacent(const T& u, const T& v) { if (contains(u) && contains(v) && u != v) { for (auto edge : adj[u]) if (edge.vertex == v) return true; } return false; } template void Graph::add_vertex(const T& u) { if (!contains(u)) { set> edge_list; adj[u] = edge_list; } } template void Graph::add_edge(const T& u, const T& v, int weight) { if (!adjacent(u, v)) { adj[u].insert(Edge(v, weight)); adj[v].insert(Edge(u, weight)); } } template void Graph::change_weight(const T& u, const T& v, int weight) { if (contains(u) && contains(v)) { if (adj[u].find(Edge(v)) != adj[u].end()) { adj[u].erase(Edge(v)); adj[u].insert(Edge(v, weight)); } if (adj[v].find(Edge(u)) != adj[v].end()) { adj[v].erase(Edge(u)); adj[v].insert(Edge(u, weight)); } } } template void Graph::remove_weight(const T& u, const T& v) { if (contains(u) && contains(v)) { if (adj[u].find(Edge(v)) != adj[u].end()) { adj[u].erase(Edge(v)); adj[u].insert(Edge(v, 0)); } if (adj[v].find(Edge(u)) != adj[v].end()) { adj[v].erase(Edge(u)); adj[v].insert(Edge(u, 0)); } } } template void Graph::remove_vertex(const T& u) { if (contains(u)) { for (auto& vertex : adj) { if (vertex.second.find(Edge(u)) != vertex.second.end()) vertex.second.erase(Edge(u)); } adj.erase(u); } } template void Graph::remove_edge(const T& u, const T& v) { if (u == v || !contains(u) || !contains(v)) return; if (adj[u].find(Edge(v)) != adj[u].end()) { adj[u].erase(Edge(v)); adj[v].erase(Edge(u)); } } template int Graph::degree(const T& u) { if (contains(u)) return adj[u].size(); return -1; // 度数为-1说明图中没有该顶点 } template int Graph::num_vertices() { return adj.size(); } template int Graph::num_edges() { int count = 0; set> vertex_set; for (auto vertex : adj) { vertex_set.insert(Edge(vertex.first, 0)); for (auto edge : vertex.second) { if (vertex_set.find(edge) != vertex_set.end()) continue; count++; } } return count; } template int Graph::largest_degree() { if (num_vertices() == 0) return 0; unsigned max_degree = 0; for (auto vertex : adj) { if (vertex.second.size() > max_degree) max_degree = vertex.second.size(); } return max_degree; } template int Graph::get_weight(const T& u, const T& v) { if (contains(u) && contains(v)) { for (Edge edge : adj[u]) if (edge.vertex == v) return edge.weight; } return -1; } template vector Graph::get_vertices() { vector vertices; for (auto vertex : adj) vertices.push_back(vertex.first); return vertices; } template void Graph::show_neighbours(const T& u) { for (const auto& v : adj[u]) cout << "[->城堡" << v.vertex << "(" << this->wealth[v.vertex - 'A'] << "): 危险值: " << v.weight << "]"; cout << endl; } template string Graph::get_neighbours(const T& u) { string a = ""; for (const auto& v : adj[u]) a += v.vertex; return a; } template int Graph::get_wealth(const T u) { return wealth[u - 'A']; } template string Graph::dijkstra(const T start) { int size = this->num_vertices(); cout << size; // 设置dis用来存放初始点到图中任何一个顶点的距离 map dis; // 设置带权重的队列,按每个pair的第一个元素进行从小到大的排列 priority_queue, vector>, greater>> q; for (T vertex : get_vertices()) { // 设置初始顶点到自己的距离为0 if (vertex == start) dis[start] = 0; // 设置初始顶点到其他顶点的距离为无穷大 else dis[vertex] = INT_MAX; } // 设置集合visited来存放已经访问过的顶点 set visited; // 入队:入队的元素是一个pair类型,第一个值是权重,第二个值是顶点 q.push(make_pair(0, start)); while (!q.empty()) { // 队首元素出队 auto front = q.top(); q.pop(); // 获得当前顶点 T u = front.second; // 如果该顶点已经访问过则跳过本此循环,否则存入到集合visited中表示已经访问过 if (visited.find(u) != visited.end()) continue; else visited.insert(u); // 获得到顶点u的最短路径"shortest_distance_to_u",将此路径存入到dis结果中 int shortest_distance_to_u = front.first; dis[u] = shortest_distance_to_u; // 依次访问顶点u尚未访问过的邻居 for (auto v : adj[u]) { if (visited.find(v.vertex) == visited.end()) { // 从顶点u到邻居v的路径记为“distance_to_v” int distance_to_v = v.weight; q.push(make_pair(shortest_distance_to_u + distance_to_v, v.vertex)); } } } return "1"; }