迪杰斯特拉算法_优化版

迪杰斯特拉优化版本:vector + 优先队列

△迪杰斯特拉算法的核心:每次找距离s点最短的元素 + 松弛操作

①要用优先队列取出最短距离降低时间复杂度,用veotor减少空间

②定义一个pair类型,作为优先队列的元素。typedef pair<int , int > P ,first是距离,second是边的终点

③pair类型作为优先队列的元素时,默认排序是先排序first,后再排序second。(升序)

因此,距离是first,边的终点是second,不可调换

 

#include <stdio.h>
#include <queue>
#include <string.h>
#define MAX 100


using namespace std;

typedef pair<int,int> P;        //first:dis[i]  second:下标i,边的终点
vector<P> map[MAX];                //不能先下标后权值,因为pair先排序first后排序second  
int vis[MAX];
int dis[MAX];
priority_queue<P, vector<P>, greater<P> > q;
const int INF = 0x3f3f3f3f;

void Dijkstra(int s, int n){
    memset(dis,INF,sizeof(dis));        
    memset(vis,0,sizeof(vis));
    dis[s]=0;
    q.push(P(0,s));        //将起始点push入队列 
    while(!q.empty()){
        P p =q.top();    //每次取最小元素
        q.pop();        //出队
        int u=p.second;
        if(vis[u])    continue;
        vis[u]=1;
        for(int i=0;i<map[u].size();i++){        //i并不是边的终点,只是顺序存储的东西 
            int v=map[u][i].second;                //获取边的终点v
            int w=map[u][i].first;                 //获取u到v的距离 
            if(!vis[v]){
                if(dis[v]>dis[u]+w){
                    dis[v]=dis[u]+w;
                    q.push(P(dis[v],v));       //松弛操作过的元素入队
                }    
            }
        }
    }
}

int main(){
    int n,m,s;
    int u,v,w;
    while(scanf("%d %d %d",&n,&m,&s)!=EOF){            //顶点数n, 边数m, 起始点s 
        for(int i=1;i<=n;i++)
            map[i].clear();        //清空vector  注意 vector 不能用二维数组初始化    
        for(int i=0;i<m;i++){
            scanf("%d %d %d",&u,&v,&w);
            map[u].push_back({w,v});        //无向图 
            map[v].push_back({w,u});        //有向图只push一次 
        }
        Dijkstra(s,n);
        for(int i=1;i<=n;i++)
            printf("%d    ",dis[i]);
    }
    return 0;
}
posted @ 2020-01-11 19:02  北冥有鱼兮  阅读(441)  评论(0编辑  收藏  举报