#include <iostream>
#include <list>
#include <map>
#include <vector>
#include <string>
#include <set>
using namespace std;
typedef int vertex_t;
typedef double weight_t;
struct edge {
vertex_t target;
weight_t weight;
edge( vertex_t v, weight_t w):target(v),weight(w){}
}; //Definition of the edge structure.
template <typename T1, typename T2>
struct comparator
{
bool operator()( pair<T1, T2> p1, pair<T1, T2> p2)
{
return p1.first < p2.first;
}
}; //The comparator used for sorting the edge weights.
typedef map<vertex_t, list<edge>> adjacentList; //The adjacent list representation of the undirected weighted graph.
typedef map<vertex_t, weight_t> minDistance; //Store the minimum distances from source to each target vertex.
typedef map<vertex_t, vertex_t> previousVertex; //Store the previous vertex of the current vertex that by travelling through gives the munimum distance to the source.
typedef set<pair<weight_t, vertex_t>, comparator<weight_t, vertex_t>> sortedEdges; //The edges are sorted for the Dijkstra algorithm by using a STL set container with self-defined comparator.
void DijkstraShortestPath(vertex_t source, adjacentList & graph, minDistance & distances, previousVertex & previous); //Function for calculating the shortest distance to the source for each vertex and storing the previous vertex in the shortest path.
void PrintShortestPaths(vector<string> & places, adjacentList & graph, minDistance & distances, previousVertex & previous);
int main(int argc, const char* agrv[])
{
adjacentList graph;
vector<string> vertexNames;
vertexNames.push_back("Harrisburg"); // 0
vertexNames.push_back("Baltimore"); // 1
vertexNames.push_back("Washington"); // 2
vertexNames.push_back("Philadelphia"); // 3
vertexNames.push_back("Binghamton"); // 4
vertexNames.push_back("Allentown"); // 5
vertexNames.push_back("New York"); // 6
graph[0].push_back(edge(1, 79.83));
graph[0].push_back(edge(5, 81.15));
graph[1].push_back(edge(0, 79.75));
graph[1].push_back(edge(2, 39.42));
graph[1].push_back(edge(3, 103.00));
graph[2].push_back(edge(1, 38.65));
graph[3].push_back(edge(1, 102.53));
graph[3].push_back(edge(5, 61.44));
graph[3].push_back(edge(6, 96.79));
graph[4].push_back(edge(5, 133.04));
graph[5].push_back(edge(0, 81.77));
graph[5].push_back(edge(3, 62.05));
graph[5].push_back(edge(4, 134.47));
graph[5].push_back(edge(6, 91.63));
graph[6].push_back(edge(3, 97.24));
graph[6].push_back(edge(5, 87.94));
minDistance distances;
previousVertex previousVertices;
DijkstraShortestPath(0, graph, distances, previousVertices);
PrintShortestPaths(vertexNames, graph, distances, previousVertices);
return 0;
}
void DijkstraShortestPath(vertex_t source, adjacentList & graph, minDistance & distances, previousVertex & previous)
{
//Initialize the distances of all the target vertices to the source to a positive infinite.
for(auto iter: graph)
distances[iter.first] = numeric_limits<weight_t>::infinity();
distances[source] = 0;
sortedEdges edgeSet; //Use STL set to overcome duplicates of the (distance, target) pairs.
for(auto iter: graph)
{
pair<weight_t, vertex_t> wrapper(distances[iter.first], iter.first);
edgeSet.insert(wrapper);
}
while(!edgeSet.empty())
{
vertex_t current = edgeSet.begin()->second;
edgeSet.erase(edgeSet.begin());
//Visiting each vertex connecting to "current". At beginning, "current" is the source vertex based on the graph initialization procedure in the main() function.
for(auto iter: graph[current])
{
vertex_t neighbor = iter.target;
weight_t weightToNeighbor = iter.weight;
//Core of the Dijkstra Shortest Paht algorithm.
weight_t distanceThroughCurrent = distances[current] + weightToNeighbor;
if(distanceThroughCurrent < distances[neighbor])
{
//Remove the (distance, target) pair from the set, and readd it to the set later on, to let set perform its sorting procedure.
pair<weight_t, vertex_t> wrapper(distances[neighbor], neighbor);
edgeSet.erase(wrapper);
distances[neighbor] = distanceThroughCurrent;
previous[neighbor] = current;
//Readd.
wrapper.first = distances[neighbor];
edgeSet.insert(wrapper);
}
}
}
return;
}
void PrintShortestPaths(vector<string> & places, adjacentList & graph, minDistance & distances, previousVertex & previous)
{
for(auto iter: graph)
{
cout << "Distance to " << places[iter.first] << ": " << distances[iter.first] << endl;
list<vertex_t> path;
path.push_front(iter.first);
previousVertex::iterator prev;
vertex_t current = iter.first;
while((prev = previous.find(current)) != previous.end())
{
current = prev->second;
path.push_front(current);
}
cout << "Path is: ";
list<vertex_t>::iterator iterPath = path.begin();
cout << places[*iterPath++];
for(;iterPath != path.end(); iterPath++)
cout << " -> " << places[*iterPath];
cout << endl << endl;
}
return;
}
结果: