Dijkstra算法堆优化求最短路径问题
——HM
Dijkstra算法在竞赛中较为常见了,(但终究没有SPFA跑得快)堆优化后更是使它的效率更上了一层楼(又是能超过SPFA),那么怎样进行堆优化呢?
还不会纯Dijkstra的人点这Dijkstra。
堆优化的Dijkstra算法就是用堆每次弹出最小值来代替每轮要进行的最短边的查找。直接搜索的时间复杂度为O(m),而堆优化后会降到O(logm),大大减小了时间复杂度。
下面来讲一下堆优化后的Dijkstra时间复杂度。这点上很多人都议论纷纷,有的说O(MlogM),有的说(MlogN),有的说O((M+N)logM),而我个人比较赞同O((M+N)logM),其中M为边数,N为点数,我们可以知道,堆搜索最短边复杂度为O(MlogM),因为要搜索单点所到的所有边,所以堆中有M个点代表边权,所以在跑最短路时复杂度为O(MlogM),而开头要初始化堆 所用时间为O(NlogM),加起来便成为了O((M+N)logM)。当然这只是个人观点,如有不同意见欢迎在讨论区中发表高见。
最后时标程,由于本人水平不高且懒惰,用邻接矩阵来储存且用的是STL中的优先级队列,没有写手打堆,这里建议用邻接表或链式前向星来储存。
AC代码:
#include <bits/stdc++.h>
const int INF=0x3f3f3f3f;
using namespace std;
struct node{
int data,pos;
node(int x,int y){data=x;pos=y;}
bool operator <(const node &a) const {
return data>a.data;
}
};
vector<pair<int,int> >GV[10001];
priority_queue<node>Q;
int dist[10001],n;
bool visited[10001];
void dij(int m){
for (int i=1;i<=n;i++)
dist[i]=INF;
dist[m]=0;Q.push(node(0,m));
while (!Q.empty()){
node temp=Q.top();Q.pop();
if (visited[temp.pos]) continue;
int pos=temp.pos,data=temp.data;
for (int i=0;i<GV[pos].size();i++)
if (data+GV[pos][i].second<dist[GV[pos][i].first]){
dist[GV[pos][i].first]=data+GV[pos][i].second;
Q.push(node(dist[GV[pos][i].first],GV[pos][i].first));
}
visited[pos]=true;
}
}
int main(){
int v,m,x,y,data;
cin>>n>>v>>m;
for (int i=1;i<=v;i++){
cin>>x>>y>>data;
GV[x].push_back(make_pair(y,data));
}
dij(m);
for (int i=1;i<=n;i++)
cout<<dist[i]<<' ';
cout<<endl;
return 0;
}
谢谢观看。