最短路径的dijkstra算法
1 #include <iostream> 2 #include <map> 3 #include <fstream> 4 #include <set> 5 #include <vector> 6 #include <algorithm> 7 #include <stack> 8 9 using namespace std; 10 11 class directedEdge{ 12 private: 13 int v; 14 int w; 15 double weight; 16 public: 17 directedEdge(int v, int w, double weight):v(v),w(w),weight(weight){} 18 directedEdge() = default; 19 directedEdge(const directedEdge &) = default; 20 int from() const {return v;} 21 int to() const {return w;} 22 double getWeight() const {return weight;} 23 bool operator<(const directedEdge &de) const {return weight < de.weight;} 24 void show() const {cout << "v: " << v << " w: " << w << " weight: " << weight << endl;} 25 virtual ~directedEdge(){} 26 }; 27 28 class directedWeightGraph{ 29 private: 30 int V; 31 int E; 32 map<int, set<directedEdge>> adj; 33 public: 34 directedWeightGraph() = default; 35 directedWeightGraph(ifstream &in); 36 set<int> getAllv() const; 37 set<directedEdge> getAdj(int v); 38 void addEdge(int v, int w, double weight); 39 void show() const; 40 virtual ~directedWeightGraph(){} 41 }; 42 43 directedWeightGraph::directedWeightGraph(ifstream &in){ 44 in >> V >> E; 45 int v, w; 46 double weight; 47 while(in >> v >> w >> weight){ 48 addEdge(v, w, weight); 49 } 50 } 51 52 set<directedEdge> directedWeightGraph::getAdj(int v) { 53 return adj[v]; 54 } 55 56 set<int> directedWeightGraph::getAllv() const { 57 set<int> temp; 58 for(auto &item : adj){ 59 temp.insert(item.first); 60 } 61 62 return temp; 63 } 64 65 void directedWeightGraph::show() const { 66 for(auto &item : adj){ 67 cout << "vertex: " << item.first << endl; 68 for(auto &edge : item.second){ 69 edge.show(); 70 } 71 } 72 } 73 74 void directedWeightGraph::addEdge(int v, int w, double weight){ 75 directedEdge de(v, w, weight); 76 if(adj.find(v) == adj.end()){ 77 adj[v] = set<directedEdge>{de}; 78 } 79 else{ 80 adj[v].insert(de); 81 } 82 } 83 84 class dijkstraSP{ 85 private: 86 map<int, double> dist; // dist[w]表示从start 到 w 所需最低成本(组成从start到w的最小路径的所有edge的weight之和) 87 map<int, directedEdge> edgeTo; //注意edgeTo的key是edge的指入端 88 set<int> que; 89 map<int, bool> marked; 90 directedWeightGraph dwg; 91 int seed; 92 int getMin(); 93 public: 94 dijkstraSP(const directedWeightGraph &dwg, int s); 95 dijkstraSP() = delete; 96 void relax(int v); // v为指出端 97 bool hasPathTo(int v) {return dist[v] != INT32_MAX;} // 注意这里尾部不能加const,否则就自相矛盾了(下面的showPathTo同理) 98 void showPathTo(int w); 99 }; 100 101 dijkstraSP::dijkstraSP(const directedWeightGraph &_dwg, int s):dwg(_dwg), seed(s) { 102 auto allVertex = dwg.getAllv(); 103 //int seed = *allVertex.begin(); 104 for(auto &item : allVertex){ 105 dist[item] = INT32_MAX; 106 marked[item] = false; 107 } 108 dist[seed] = 0.0; 109 que.insert(seed); 110 while(que.size()!=0){ 111 /* 一定是选择当前dist中最小的那个点 minior 来作为relax的入参, 112 因为如果从start到达minior还有其他成本更低的路径的话,早就在当前这次循环前就处理了(因为每次循环都是选出dist最小的点来作为relax入参的) */ 113 relax(getMin()); 114 } 115 } 116 117 int dijkstraSP::getMin(){ 118 int minior; 119 double weight = INT32_MAX; 120 for_each(que.begin(), que.end(), [&](const auto &item){if(dist[item] < weight){weight = dist[item]; minior = item;}}); 121 que.erase(minior); 122 return minior; 123 } 124 125 void dijkstraSP::relax(int v){ 126 marked[v] = true; 127 auto alle = dwg.getAdj(v); 128 for(auto &edge : alle){ 129 int w = edge.to(); 130 if(marked[w])continue; 131 if(dist[w] > dist[v] + edge.getWeight()){ 132 dist[w] = dist[v] + edge.getWeight(); 133 edgeTo[w] = edge; 134 } 135 /* 不像书里(P423)那样,这里把加入que的流程放到前面的if外,所以前面需要用marked来辅助过滤掉已处理的点(否则构造函数中的while就有可能会死循环(当存在自环时)) */ 136 if(que.find(w) == que.end()) 137 que.insert(w); 138 } 139 } 140 141 void dijkstraSP::showPathTo(int w) { 142 if(!hasPathTo(w)){ 143 cout << "there is no path from " << seed << " to " << w << "!" << endl; 144 return; 145 } 146 stack<int> st; 147 st.push(w); 148 while(st.top()!=seed){ 149 st.push(edgeTo[st.top()].from()); 150 } 151 cout << "the path: "; 152 while(!st.empty()){ 153 cout << st.top() << " "; 154 st.pop(); 155 } 156 cout << endl; 157 158 } 159 160 int main(){ 161 ifstream in("/home/tanweimin/code/program_practice/ALGORITHM/sort/tinyEWD.txt"); 162 directedWeightGraph dwg(in); 163 dwg.show(); 164 dijkstraSP djsp(dwg, 5); 165 djsp.showPathTo(6); 166 djsp.showPathTo(2); 167 djsp.showPathTo(4); 168 }
预期结果:
the path: 5 1 3 6 the path: 5 1 3 6 2 the path: 5 4
tinyEWD.txt
8 15 4 5 0.35 5 4 0.35 4 7 0.37 5 7 0.28 7 5 0.28 5 1 0.32 0 4 0.38 0 2 0.26 7 3 0.39 1 3 0.29 2 7 0.34 6 2 0.4 3 6 0.52 6 0 0.58 6 4 0.93