• 【算法】Dijkstra算法(单源最短路径问题)(路径还原) 邻接矩阵和邻接表实现


    Dijkstra算法可使用的前提:不存在负圈。

    负圈:负圈又称负环,就是说一个全部由负权的边组成的环,这样的话不存在最短路,因为每在环中转一圈路径总长就会边小。

    算法描述:

      1.找到最短距离已确定的顶点,从它出发更新相邻顶点的最短距离。

      2.以后不需要再关心1中的“最短距离已确定的顶点”。

    C++代码:

    #include <bitsstdc++.h>
    using namespace std;
    #define INF 2147483647
    #define MAX_V 1000
    #define MAX_E 2000 
    
    //单源最短路径问题(Dijkstra算法) 
    
    
    int cost[MAX_V][MAX_V];  //cost[u][v]表示e = (u,v)的权值 
    int d[MAX_V];        //顶点s出发的最短距离 
    bool used[MAX_V];    //标记使用过的点 
    int V;          //顶点数 
    
    void dijkstra(int s){
        fill(d, d+V, INF);
        fill(used, used + V, false);
        d[s] = 0;
        
        while(true){
            int v = -1;
            
            //找到一个距离最近的没有使用过的点 
            for(int u = 0;u < V; u++){
                if(!used[u] && (v == -1 || d[u] < d[v])) v = u;
            }
            //如果所有的点都被使用过了,则break
            if(v == -1) break;
            
            //标记当前点被使用过了 
            used[v] = true;
            
            //更新这个找到的距离最小的点所连的点的距离 
            for(int u = 0;u < V; u++){
                d[u] = min(d[u], d[v] + cost[v][u]);
            }
            
        }
    }
    
    
    int main(){
    } 

    我们会发现,如果边比较少的话,用邻接矩阵特别耗时间和空间。

    时间复杂度O(V^2)

    所以边比较少的话,有一种邻接矩阵的写法,对其优化一下,

    时间复杂度O(E*log(V))

    C++代码:

    #include <bitsstdc++.h>
    using namespace std;
    #define INF 2147483647
    #define MAX_V 1000
    #define MAX_E 2000 
    
    //单源最短路径问题(Dijkstra算法) 
    
    struct edge{
        int to,cost;
    };    
    
    typedef pair<int, int> P;  //first是最短距离,second是顶点的编号 
    
    int V;    //顶点数 
    vector <edge> G[MAX_V];   //
    int d[MAX_V];            // d[i]表示i离源点的最短距离 
    
    
    
    void dijkstra(int s){
        //通过指定greater<P> 参数,优先队列是用堆实现的,堆按照first从小到大排序。 
        priority_queue<P, vector<P>, greater<P> > que;
        
        fill(d, d+V, INF);
        d[s] = 0;
        
        //加源点入最小堆 
        que.push(P(0,s));
        
        while(!que.empty()){
            //取出堆顶的点,也就是距离最小的点 
            P p = que.top(); que.pop();
            int v = p.second;
            
            //如果这个点在加入队列之后更新过,就不必再更新 
            if(d[v] < p.first) continue;
            
            //遍历当前点相邻的所有点 
            for(int i = 0;i < G[v].size(); i++){
                edge e = G[v][i];
                //如果这个点能更新其他点,就将被更新的那个点加入队列。 
                if(d[e.to] > d[v] + e.cost){
                    d[e.to] = d[v] + e.cost;
                    que.push(P(d[e.to], e.to));
                }    
            }    
        }
    }
    
    int main(){
    } 

    路径还原:

    #include <bitsstdc++.h>
    using namespace std;
    #define INF 2147483647
    #define MAX_V 1000
    #define MAX_E 2000 
    
    //单源最短路径问题(Dijkstra算法) 
    
    
    int cost[MAX_V][MAX_V];  //cost[u][v]表示e = (u,v)的权值 
    int d[MAX_V];        //顶点s出发的最短距离 
    bool used[MAX_V];    //标记使用过的点 
    int V;          //顶点数 
    
    int prev[MAX_V];  //最短路径上的前驱顶点 
    
    void dijkstra(int s){
        fill(d, d+V, INF);
        fill(used, used + V, INF);
        fill(prev, prev+V, -1); //初始化前驱数组 
        d[s] = 0;
        
        while(true){
            int v = -1;
            for(int u = 0;u < V; u++){
                if(!used[u] && (v == -1 || d[u] < d[v])) v = u;
            }
            if(v == -1) break;
            used[v] = true;
            for(int u = 0;u < V; u++){
                d[u] = min(d[u], d[v] + cost[v][u]);
                prev[u] = v;    //记录每个点的前驱 
            }
        }
    }
    
    //获取起始点到顶点t的最短路径 
    vector <int> getpath(int t){
        vector<int> path;
        while(t != -1){
            path.push_back(t);
            t = prev[t];
        }
        //获取的路径是逆序,需要翻转 
        reverse(path.begin(),path.end());
        
        return path;
    }
    
    
    int main(){
    } 
  • 相关阅读:
    AWS CLI command example
    NetTime
    git fetch和git pull的区别
    Coding tools
    Username Generator
    使用消息系统来解决分布式事务
    【转】关于分布式事务、两阶段提交协议、三阶提交协议
    NoSql的三大基石:CAP理论&BASE&最终一致性
    【转】Raft 为什么是更易理解的分布式一致性算法
    【转】分布式一致性算法:Raft 算法(Raft 论文翻译)
  • 原文地址:https://www.cnblogs.com/zhangjiuding/p/7712592.html
Copyright © 2020-2023  润新知