#include <iostream>
#include <queue>
#include <map>
#include <utility>
#include <climits>
using namespace std;
typedef int graph_weight_t;
typedef char graph_vertex_id_t;
struct graph_t {
int nv;
int ne;
map<graph_vertex_id_t, map<graph_vertex_id_t, graph_weight_t> > matrix;
};
/**
* @param[in] start 起点
* @param[out] dist dist[v] 存放的是起点到v 的最短路径长度
* @param[out] father father[v] 存放的是最短路径上指向v 的上一个顶点
*/
void dijkstra(const graph_t &g, graph_vertex_id_t start,
map<graph_vertex_id_t, graph_weight_t> &distance,
map<graph_vertex_id_t, graph_vertex_id_t> &father) {
/* 起点到顶点的最短距离. */
typedef pair<graph_weight_t, graph_vertex_id_t> to_dist_t;
// 小根堆
priority_queue<to_dist_t, vector<to_dist_t>, greater<to_dist_t> > q;
distance[start] = 0; // 自己到自己,距离为0
q.push(to_dist_t(0, start));
while (!q.empty()) {
const to_dist_t u = q.top(); q.pop();
if (g.matrix.find(u.second) == g.matrix.end()) continue;
for (map<graph_vertex_id_t, graph_weight_t>::const_iterator iter =
g.matrix.at(u.second).begin();
iter != g.matrix.at(u.second).end(); ++iter) {
const graph_vertex_id_t v = iter->first;
const graph_weight_t w = iter->second;
if (!distance.count(v) || distance[u.second] + w < distance[v]) {
distance[v] = distance[u.second] + w;
father[v] = u.second;
q.push(to_dist_t(distance[v], v));
}
}
}
return;
}
/**
* @brief 打印从起点到终点的最短路径
* @param[in] father Dijkstra 计算好的father 数组
* @param[in] end 终点
*/
void print_path(const map<graph_vertex_id_t, graph_vertex_id_t> &father,
graph_vertex_id_t end) {
if (!father.count(end)) {
cout << end;
} else {
print_path(father, father.at(end));
cout << "->" << end;
}
}
/** 读取输入,构建图. */
void read_graph(graph_t &g) {
cin >> g.ne;
for (int i = 0; i < g.ne; ++i) {
graph_vertex_id_t from, to;
graph_weight_t weight;
cin >> from >> to >> weight;
g.matrix[from][to] = weight;
}
}
int main() {
graph_t g;
map<graph_vertex_id_t, graph_weight_t> distance;
map<graph_vertex_id_t, graph_vertex_id_t> father;
read_graph(g);
dijkstra(g, 'A', distance, father);
// 输出所有路径
for(map<graph_vertex_id_t, graph_vertex_id_t>::const_iterator iter =
father.begin(); iter != father.end(); ++iter) {
if (iter->first != 'A') {
print_path(father, iter->first);
cout << endl;
}
}
return 0;
}
/* test
输入数据:
8
A C 10
A E 30
A F 100
B C 5
C D 50
D F 10
E D 20
E F 60
输出:
A->C
A->E->D
A->E
A->E->D->F
*/
单源最短路径(dijkstra算法)
最新推荐文章于 2020-06-09 10:24:23 发布