dijkstra(数组实现n²,带打印路径)
算法思想(参考某算法模板,不知道挂哪的链接,纯属记录)
Dijkstra算法采用的是一种贪心的策略,声明一个数组lowcost来保存源点到各个顶点的最短距离和一个保存已经找到了最短路径的顶点的集合:T(用vis数组来标记),path存储路径前驱。
- 初始化,vis[i] = 0, lowcost[i] = INF, cost[i] [j] = INF, cost[i] [i] = 0。
- 初始时,lowcost[beg] = 0,vis[beg] = 1, path[beg] = -1。经过n-1轮,每轮选出一个距离源点最近的点u作为桥梁(可用堆来优化),如果lowcost[u] + cost[u] [j] < lowcost[j],就更新并且记录路径。选取u前设为-1,如果选取完之后u == -1,则无法到达目标点;期间如果找到了目标点可直接返回。
- 打印路径需要逆序打印,这里用的递归。
/*==================================================*\
| Dijkstra 数组实现 O(N^2)
| Dijkstra --- 数组实现(在此基础上可直接改为STL的Queue实现)
| lowcost[] --- beg到其他点的最近距离
| path[] -- beg为根展开的树,记录父亲结点
\*==================================================*/
#include<bits/stdc++.h>
using namespace std;
#define INF 0x03F3F3F3F
#define N 105
int path[N], vis[N], cost[N][N], lowcost[N], n, m;
void init(){
for (int i = 0; i < n; ++i){
for (int j = 0; j < n; ++j){
if (i == j)
cost[i][j] = 0;
else
cost[i][j] = INF;
}
lowcost[i] = INF;
vis[i] = 0;
}
}
void intput(){
//cin >> n >> m;
for (int i = 0; i < m; i++){
int u, v, w;
cin >> u >> v >> w;
cost[u-1][v-1] = cost[v-1][u-1] = w;
}
}
void output(int beg, int end){
cout << lowcost[end] << endl;
}
void print(int k){ //打印路径
if (-1 != k){
print(path[k]);
cout << k+1 << ' ';
}
}
bool Dijkstra(int beg, int end){
vis[beg] = 1;
for (int i = 0; i < n; i++)
lowcost[i] = cost[beg][i];
lowcost[beg] = 0;
path[beg] = -1; // 树根的标记
for (int i = 1; i < n; i++){
int u = -1;
for (int j = 0; j < n; j++)
if (vis[j] == 0 && (u == -1 || lowcost[j] < lowcost[u]))
u = j;
if (u == -1) return 0;
if (u == end) return 1;
vis[u] = 1;
for (int j = 0; j < n; j++)
// 下面的加法可能导致溢出,INF不能取太大
if (vis[j] == 0 && lowcost[u] + cost[u][j] < lowcost[j]){
lowcost[j] = lowcost[u] + cost[u][j];
path[j] = u;
}
}
return 1;
}
int main(){
while (cin >> n >> m){
if (n == 0 && m == 0) return 0;
init();
intput();
if (Dijkstra(0, n-1)) // 0:起点 n-1终点
//for (int i = 0; i < n; i++)
output(0, n-1);
//print(n-1);
}
}
题目链接u.edu.cn/showproblem.php?pid=2544)