先友情提示一下,作者很早就会这个算法了,只不过这么久以来没怎么写过博客。现在正在学习它的拓展,干脆就把这个算法相关的内容整个敲一遍吧!本章把迪杰斯特拉从基础到拓展全都说一遍咯。
下面是优先队列(堆)优化后的dij代码。
#include<queue>
#include<vector>
#define inf 0x3f3f3f
struct Edge{
int to,dis; //to表示目标点,dis表示边的权值
};
struct HeapNode{ //记录dij算法用到的优先队列中的节点
int d,u;
bool operator <(const HeapNode& rhs) const{
return d>rhs.d;
}
};
struct Dijkstra{
int n,m;
vector<Edge> edges; //边列表
vector<int> G[maxn]; //每个节点的出边的编号,也可以手写邻接表(没开O2的话建议手写)
int d[maxn],p[maxn]; //d[i]表示起点s到i的最短距离,p[i]表示从s到i最短路中的上一条边
void init(int n){
this->n = n;
for(int i=0;i<n;i++) G[i].clear(); // 清空邻接表
edges.clear(); //清空边表
}
void Addedge(int from,int to,int dis){
edges.push(back(Edge){to,dist});
m=edges.size();
G[from].push_back(m-1);
}
void dij(int s){ //求起点s到所有点的距离
priority_queue<Heapnode> q;
for(int i=0;i<n;i++) d[i]=inf;
d[s]=0;
q.push((HeapNode){0,s});
while(!q.empty()){
Heapnode x=q.top(); q.pop();
int u=x.u;
if(d[i]!=inf) continue; //已经被确定过距离的点不再重复确定
for(int i=0;i<G[u].size();i++){
Edge& e=edges[G[u][i]]; //引用符号(&)相当于在循环中用e代替了edges[G[u][i]],任何对e的调用和赋值都会转成edges[G[u][i]]
if(d[e.to]>d[u]+e.dis){ //新距离比历史距离更短,更新
d[e.to]d[u]+e.dis;
p[e.to]=G[u][i];
q.push((HeapNode){d[e.to],e.to});
}
}
}
}
};