#include <iostream> #include <string> #include <queue> #include <functional> #include <vector> #include <algorithm> #pragma warning(disable:4996) #define VERTEX 13 using namespace std;
struct MinHeap { int vertexID; int distance; bool operator > (const MinHeap &vertex) const { return this->distance > vertex.distance; } };
struct Arcs { int u; int v; int w; };
struct AdjacencyMatrix { string vertex[VERTEX]; int edges[VERTEX][VERTEX]; int isTraversed[VERTEX]; int parent[VERTEX]; int distance[VERTEX]; int rank[VERTEX]; int nArcs; Arcs arcs[VERTEX*VERTEX]; MinHeap key[VERTEX]; };
void createGraph(AdjacencyMatrix &graph) { int map[VERTEX][VERTEX] = { { 0, 75, -1,118, -1, -1, -1,140, -1, -1, -1, -1, -1 }, { -1, 0, 71, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, { -1, -1, 0, -1, -1, -1, -1,151, -1, -1, -1, -1, -1 }, { -1, -1, -1, 0,111, -1, -1, -1, -1, -1, -1, -1, -1 }, { -1, -1, -1, -1, 0, 70, -1, -1, -1, -1, -1, -1, -1 }, { -1, -1, -1, -1, -1, 0, 75, -1, -1, -1, -1, -1, -1 }, { -1, -1, -1, -1, -1, -1, 0, -1, -1,120, -1, -1, -1 }, { -1, -1, -1, -1, -1, -1, -1, 0, 80, -1, 99, -1, -1 }, { -1, -1, -1, -1, -1, -1, -1, -1, 0,146, -1, 97, -1 }, { -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1,138, -1 }, { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1,211 }, { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0,101 }, { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0 } }; graph.nArcs = 0; for (int i = 0; i < VERTEX; i++) for (int j = i; j < VERTEX; j++) if (map[i][j] != -1) { map[j][i] = map[i][j]; graph.arcs[graph.nArcs] = Arcs{ i, j, map[i][j] }; graph.arcs[graph.nArcs + 1] = Arcs{ j, i, map[j][i] }; graph.nArcs += 2; } memcpy(graph.edges, map, sizeof(map)); graph.vertex[0] = "Arad"; graph.vertex[1] = "Zerind"; graph.vertex[2] = "Oradea"; graph.vertex[3] = "Timisoara"; graph.vertex[4] = "Lugoj"; graph.vertex[5] = "Mehadia"; graph.vertex[6] = "Drobeta"; graph.vertex[7] = "Sibiu"; graph.vertex[8] = "Rimnicu-Vilcea"; graph.vertex[9] = "Craiova"; graph.vertex[10] = "Fagaras"; graph.vertex[11] = "Pitesti"; graph.vertex[12] = "Bucharest"; for (int i = 0; i < VERTEX; i++) graph.isTraversed[i] = 0; }
void outputGraph(AdjacencyMatrix &graph) { for (int i = 0; i < VERTEX; i++) for (int j = 0; j < VERTEX; j++) if (graph.edges[i][j] > 0) cout << graph.vertex[i] << " -> " << graph.vertex[j] << " : " << graph.edges[i][j] << endl; }
void initializeSingleSource(AdjacencyMatrix &graph, int s) { for (int i = 0; i < VERTEX; i++) { graph.distance[i] = INT_MAX; graph.parent[i] = -1; } graph.distance[s] = 0; }
void relax(AdjacencyMatrix &graph, int u, int v) { if (graph.distance[v] > graph.distance[u] + graph.edges[u][v]) { graph.distance[v] = graph.distance[u] + graph.edges[u][v]; graph.parent[v] = u; } }
void dijkstra(AdjacencyMatrix &graph, int start) { initializeSingleSource(graph, start); priority_queue<MinHeap, vector<MinHeap>, greater<MinHeap>> q; q.push(MinHeap{ start, graph.distance[start] }); while (!q.empty()) { MinHeap vertex = q.top(); q.pop(); graph.isTraversed[vertex.vertexID] = 1; for (int i = 0; i < VERTEX; i++) { if (graph.isTraversed[i] == 0 && graph.edges[vertex.vertexID][i] > 0) { relax(graph, vertex.vertexID, i); q.push(MinHeap{ i, graph.distance[i] }); } } } }
bool bellmanFord(AdjacencyMatrix &graph, int start) { initializeSingleSource(graph, start); for (int i = 0; i < VERTEX - 1; i++) for (int j = 0; j < VERTEX; j++) for (int k = 0; k < VERTEX; k++) if (graph.edges[j][k] > 0) relax(graph, j, k); for (int i = 0; i < VERTEX; i++) for (int j = 0; j < VERTEX; j++) if (graph.edges[i][j] > 0 && graph.distance[i] > graph.distance[j] + graph.edges[i][j]) return false; return true; }
void floydWarshall(AdjacencyMatrix &graph) { for (int k = 0; k < VERTEX; k++) for (int i = 0; i < VERTEX; i++) for (int j = 0; j < VERTEX; j++) if (graph.edges[i][k] != -1 && graph.edges[k][j] != -1 && ((graph.edges[i][j] >= graph.edges[i][k] + graph.edges[k][j]) || graph.edges[i][j] == -1)) graph.edges[i][j] = graph.edges[i][k] + graph.edges[k][j]; }
void makeSet(AdjacencyMatrix &graph, int x) { graph.parent[x] = x; graph.rank[x] = 0; }
int findSet(AdjacencyMatrix &graph, int x) { if (x != graph.parent[x]) graph.parent[x] = findSet(graph, graph.parent[x]); return graph.parent[x]; }
void linkSet(AdjacencyMatrix &graph, int u, int v) { if (graph.rank[u] > graph.rank[v]) graph.parent[v] = u; else { graph.parent[u] = v; if (graph.rank[u] = graph.rank[v]) graph.rank[v]++; } }
void unionSet(AdjacencyMatrix &graph, int u, int v) { linkSet(graph, findSet(graph, u), findSet(graph, v)); }
bool compare(Arcs e1, Arcs e2) { return e1.w < e2.w; }
vector<string> kruskal(AdjacencyMatrix &graph) { vector<string> mst; for (int i = 0; i < VERTEX; i++) makeSet(graph, i); sort(graph.arcs, graph.arcs + graph.nArcs, compare); for (int i = 0; i < graph.nArcs; i++) if (findSet(graph, graph.arcs[i].u) != findSet(graph, graph.arcs[i].v)) { char *buffer = new char[10]; unionSet(graph, graph.arcs[i].u, graph.arcs[i].v); sprintf(buffer, "%d -> %d", graph.arcs[i].u, graph.arcs[i].v); mst.push_back(buffer); } return mst; }
bool prim(AdjacencyMatrix &graph) { int count = 0; priority_queue<MinHeap, vector<MinHeap>, greater<MinHeap>> q; initializeSingleSource(graph, 0); q.push(MinHeap{ 0, graph.distance[0] }); while (!q.empty()) { MinHeap u = q.top(); q.pop(); graph.distance[u.vertexID] = 0; count++; for (int i = 0; i < graph.nArcs; i++) { if (graph.arcs[i].u == u.vertexID) { if (graph.distance[graph.arcs[i].v] != 0) { if (graph.edges[graph.arcs[i].u][graph.arcs[i].v] < graph.distance[graph.arcs[i].v]) { graph.distance[graph.arcs[i].v] = graph.edges[graph.arcs[i].u][graph.arcs[i].v]; graph.parent[graph.arcs[i].v] = graph.arcs[i].u; q.push(MinHeap{ graph.arcs[i].v, graph.distance[graph.arcs[i].v] }); } } } } } if (count < VERTEX) return false; return true; }
int main(int argc, char *argv[]) { AdjacencyMatrix graph; int start = 0, end = 12; createGraph(graph); outputGraph(graph);
cout << endl << "Dijkstra" << endl; createGraph(graph); dijkstra(graph, start); for (int i = 0; i < VERTEX; i++) { int j = i; cout << graph.vertex[j]; while (graph.parent[j] != -1) { j = graph.parent[j]; cout << " <- " << graph.vertex[j]; } cout << endl; }
cout << endl << "Bellman-Ford" << endl; if (bellmanFord(graph, start)) for (int i = 0; i < VERTEX; i++) { int j = i; cout << graph.vertex[j]; while (graph.parent[j] != -1) { j = graph.parent[j]; cout << " <- " << graph.vertex[j]; } cout << endl; } else cout << "There's a negative cycle" << endl;
cout << endl << "Floyd-Warshall" << endl; createGraph(graph); floydWarshall(graph); for (int i = 0; i < VERTEX; i++) { for (int j = 0; j < VERTEX; j++) cout << graph.edges[i][j] << " "; cout << endl; }
cout << endl << "Kruskal" << endl; createGraph(graph); vector<string> mstKruskal = kruskal(graph); for (int i = 0; i < mstKruskal.size(); i++) cout << mstKruskal[i] << endl;
cout << endl << "Prim" << endl; createGraph(graph); if (prim(graph)) for (int i = 1; i < VERTEX; i++) cout << graph.parent[i] << " -> " << i << endl; else cout << "不连通,生成树不存在。" << endl;
system("pause"); return 0; }
|