dijkstra(堆优化)
算法思想(根据一算法模板实现,仅作记录)
Dijkstra算法采用的是一种贪心的策略,声明一个数组distt来保存源点到各个顶点的最短距离和一个保存已经找到了最短路径的顶点的集合:T(用vis数组来标记),preV存储路径前驱。
-
初始化,vis[i] = 0, dist[i] = INF,preV[i] = -1。创建一个优先队列q(小顶堆)来存储顶点结点,按dis大小排序。
-
起始点u入队,dist[u] = 0, vis[u] = 1,然后只要队不空且没找到所有结点的最短路径就一直出队,出队的必是最短的,将其加入集合(置1),然后根据 !vis[j] && dist[j] > temp.dis + c 更新其可达的结点的最短路径。
-
打印路径需要逆序打印,这里用的递归。
/*==================================================*\
| Dijkstra O(E * log E)
| INIT: 调用init(nv, ne)读入边并初始化;
| CALL: dijkstra(nv, u, adj); dist[i]为u到i的最短距离
\*==================================================*/
#include<bits/stdc++.h>
using namespace std;
#define typec int // type of cost
#define E 100000 //边数
#define V 1000 //顶点数
const typec inf = 0x3f3f3f3f; // max of cost
typec dist[V];
int vis[V], preV[V];
struct node { //顶点结点,v:顶点号, dis:距离源点的最短路径
int v;
typec dis;
node (int _v = 0, typec _dis = 0) : v(_v), dis(_dis) {}
bool operator < (const node& r) const {
return dis > r.dis;
}
};
struct edge{ //边表节点
int v;
typec c;
edge (int _v = 0, int _c = 0) : v(_v), c(_c) {}
};
void dijkstra(int nv, const int u, vector<edge> *adj){
priority_queue<node> q;
q.push(node(u, 0));
vis[u] = 1;
dist[u] = 0;
int cnt = 0;
while (!q.empty() && cnt <= nv){
node temp = q.top();
q.pop();
vis[temp.v] = 1; //已经求得的最短路径的顶点号置1
cnt++;
for (int i = 0; i < adj[temp.v].size(); i++){
int j = adj[temp.v][i].v;
typec c = adj[temp.v][i].c;
if (!vis[j] && dist[j] > temp.dis + c){ //由新求得最短路径的点temp.v更新其可达的点的最短路径
q.push(node(j, temp.dis+c));
dist[j] = temp.dis + c;
//preV[j] = temp.v; //保存路径
}
}
}
}
inline void addedge(int u, int v, typec& c, vector<edge> *adj){
adj[u].push_back(edge(v, c));
adj[v].push_back(edge(u, c)); //无向图
}
void init(int nv, int ne, vector<edge> *adj){
memset(vis, 0, sizeof(vis));
//memset(preV, -1, sizeof(preV));
for (int i = 0; i < nv; i++)
dist[i] = inf;
for (int i = 0; i < ne; ++i) {
int u, v;
typec c;
cin >> u >> v >> c;
addedge(u-1, v-1, c, adj); // vertex: 0 ~ n-1, 单向边
}
}
void print(int k){ //打印路径
if (-1 != k){
print(preV[k]);
cout << k << ' ';
}
}
void output(int k){
cout << dist[k] << endl;
//print(k); //打印路径
//cout << endl;
}
int main(){
int nv, ne;
while(cin >> nv >> ne){
if(nv == 0 && ne == 0)
return 0;
vector<edge> adj[nv];
init(nv, ne, adj);
dijkstra(nv, 0, adj);
//for (int i = 0; i < nv; i++)
//output(i);
output(nv-1);
}
return 0;
}