优美的堆优化的dijkstra

dijkstra算法是用来解决不带负权图上的最短路径问题,从学习这个算法来,写过最朴素的dijkstra,时间复杂度达O(N^2),也写过看似高大上的堆优化dijkstra,时间复杂度因为利用堆找最小值提高效率至O(Mlogn)。
多年来代码风格不停在变,今天在此又重新写了一遍,只为能充分利用C++STL,利用C++在语言上的优势,使堆优化版本写起来优美又简洁。
下面附上代码模版

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 200002;
const int MAXM = 400004;
int n,m,total=0,head[MAXN];
struct node{
    int v;
    int next;
    int w;
};
 //利用STL优先队列实现堆上找最小值,因为堆默认是大根堆,为了达到小根堆的效果,入距离时,入其负值。
 //利用pair这个解决两个数捆绑成一个对象的问题,其中第一个对象是距离,第二个是编号。 
priority_queue< pair<long long ,int> >q;
long long dis[MAXN];  //dis[i]存从1至i的最小值。 
bool vis[MAXN];
node edge[MAXM*2];//存所有的边 
//链式前向星存边 ,非常简洁的写法 
void addEdge(int u,int v,int w){ 
    edge[++total]=(node){v,head[u],w};
    head[u] = total;
}
void duidij(){
    //初始化 距离数组为正无穷,并对起点距离设为0,起点入队列 
    memset(dis,0x3f,sizeof(dis));
    memset(vis,false,sizeof(vis));  
    dis[1] = 0;
    q.push(make_pair(0,1));
    while(q.size()){
        int u = q.top().second; //取堆中最小值编号 
        q.pop();//出堆 
        if(vis[u]) continue;
        vis[u] = true;//设置该编号已被选做最小值作为起点 
        for(int i= head[u];i;i = edge[i].next){//枚举与u相连的所有边 
            int v = edge[i].v,w = edge[i].w; 
            if(dis[v] > dis[u] + w){//寻找可以松弛的边 
                dis[v] = dis[u] + w;  //更新距离 
                q.push(make_pair(-dis[v],v));//入堆 
            }
        }
    }
}
int main(){
    cin >> n >> m;
    for(int i = 1;i<= m;i++){
        int x,y,z;
        cin >> x >> y >> z;
        addEdge(x,y,z);addEdge(y,x,z);//无向图需要存两遍 
    }
    duidij();
    cout << dis[n];
    return 0;
}

猜你喜欢

转载自blog.csdn.net/xuechen_gemgirl/article/details/79893166