zoukankan      html  css  js  c++  java
  • 单源最短路径、所有结点对的最短路径

    算法核心:两个结点之间的一条最短路径包含着(包含于)其它的最短路径.[最短路径性质]

    1.单源最短路径Dijkstra

    思路:计算每个结点到源结点的距离,压入最小优先队列Q,对Q中的元素进行如下循环操作:

    1.从队列Q中弹出最小元素u
    2.将u并入S
    3.对u的邻接表中每个结点v,调用Relax(u,v,w)更新结点v到源结点s的距离

    直至Q为空.

    伪代码:

    Initialize-Single-Source(G,s)
        for each vertex v in G.v
            v.d = MAX
            v.p = NIL
        s.d = 0
    Realx(u,v,w)
        if v.d > u.d + w[u][v]
            v.d = u.d + w[u][v]
            v.p = u
    Dijkstra(G,w,s)
        Initialize-Single-Source(G,s)
        S = ∅//已经找到到源结点s的最短路径的结点的集合
        Q = G.V//Q是以结点到源结点距离为priority的最小优先队列
        while Q ≠ ∅
            u = EXTRACT-MIN(Q)
            S = S∪{u}
            for each vertex v in G.Adj[u]
                Relax(u,v,w)

    时间复杂度:O(|V|2)

    编码实现:

    #include<iostream>
    #include<vector>
    #include<utility>
    #include<algorithm>
    #include<queue>
    #include<set>
    #include<cassert>
    using namespace std;
    #define MAX 10000
    enum Color{white,gray,black};
    
    class Node{
    public:
        int index;
        Node* next=nullptr;//
        Node(int i):index(i){}
    };
    class VNode{
    public:
        char vertex;
        int index;
        int dist;
        int final;
        int indegree;
        Color color=white;
        int prev=-1;
        Node* firstNode=nullptr;
        VNode(char c,int i):vertex(c),index(i){}
    };
    typedef struct Graph{
        int EdgeNum;
        vector<VNode> Adj;
    }Graph;
    void initialize_single_source(Graph &G,int s,int w[][6]){
        for(auto &v:G.Adj){//use reference**************
            v.dist = MAX;//w[0][v.index];
            v.prev = -1;
        }
        G.Adj[s].dist = 0;
    }
    void relax(Graph &G,int u,int v,int w[][6]){
        if(G.Adj[v].dist > G.Adj[u].dist + w[u][v]){
            G.Adj[v].dist = G.Adj[u].dist + w[u][v];
            G.Adj[v].prev = u;
        }
    }
    //为优先队列提供比较结构,小的优先
    struct comp
    {
        bool operator () (VNode &a,VNode &b)const{
            return a.dist>b.dist;
        }
    };
    void dijkstra(Graph &G,int w[][6],int s){
        initialize_single_source(G,s,w);
        set<int> S;
        priority_queue<VNode,vector<VNode>,comp> Q;
        for(int i=0;i<G.Adj.size();i++){
            Q.push(G.Adj[i]);
        }
        while(!Q.empty()){
            int u = (Q.top()).index;
            Q.pop();
            S.insert(u);
            Node* p = G.Adj[u].firstNode;
            while(p != nullptr){
                int v = p->index;
                relax(G,u,v,w);
                p = p->next;
            }
            //由于保存在Q中的元素是结点的副本,故结点到源结点距离改变时,优先队列Q不会受到影响,也就是Q不会像我们期望的那样工作,故需重新生成Q
            priority_queue<VNode,vector<VNode>,comp> Q3;
            while(!Q.empty()){
                VNode vn=Q.top();
                Q.pop();
                Q3.push(G.Adj[vn.index]);
            }
            Q=Q3;
        }
    }
    void AddEdge(Graph &G,int i,int j){
        Node* p = new Node(j);
        p->next = G.Adj[i].firstNode;
        G.Adj[i].firstNode = p;
    }
    
    void print_path(Graph &G,int s,int v){
        if(v == s){
            cout<<G.Adj[s].vertex<<",";
        }
        else if(G.Adj[v].prev  == -1){
            cout<<"No such path!";
        }
        else{
            print_path(G, s, G.Adj[v].prev);
            cout<<G.Adj[v].vertex<<",";
        }
    }
    
    int main(){
        Graph G;
        G.EdgeNum = 8;
        vector<char> v={'a','b','c','d','e','f'};
        for(int i=0;i<v.size();i++){
            G.Adj.push_back(VNode(v[i], i));
        }
        AddEdge(G,0,2);
        AddEdge(G,0,4);
        AddEdge(G,0,5);
        AddEdge(G,1,2);
        AddEdge(G,2,3);
        AddEdge(G,3,5);
        AddEdge(G,4,3);
        AddEdge(G,4,5);
        int w[6][6];
        for (int i = 0; i < 6; ++i)
        {
            for (int j = 0; j < 6; ++j)
            {
                            if(i==j){
                                w[i][j] = 0;
                             }
                             else{
                    w[i][j] = MAX;
                             }
            }
        }
        w[0][2] = 10;
        w[0][4] = 30;
        w[0][5] = 100;
        w[1][2] = 5;
        w[2][3] = 50;
        w[3][5] = 10;
        w[4][3] = 20;
        w[4][5] = 60;
        dijkstra(G,w,0);
        for(int i=1;i<G.Adj.size();i++){
            cout<<G.Adj[i].dist<<'	';
            print_path(G,0,i);
            cout<<endl;    
        }
        return 0;
    }
    View Code

    2.所有结点对的最短路径FloydWarshall

    思路:对每对结点[i,j],尝试向中间加入结点k,如果w[i][j] > w[i][k] + w[k][j],则更新[i,j]之间的最短距离为w[i][j] = w[i][k] + w[k][j].由于k的加入使w[i][j]变小,故k属于结点对[i,j]的最短路径上的点,另外,由于最短路径性质,[i,j]的最短路径由[i,k]和[k,j]的最短l路径组成.

    伪代码:

    void FloydWarshall(Graph &G,int w[][6],int v[][6]){
        for(int k=0;k<6;k++){
            for(int i=0;i<6;i++){
                for(int j=0;j<6;j++){
                    if(w[i][j]>w[i][k]+w[k][j]){
                        w[i][j] = w[i][k]+w[k][j];
                        v[i][j] = k;//记下[i,j]的最短路径的中间结点        
                    }
                }
            }
        }
    }

    时间复杂度:O(|V|3)

    编码实现:

    #include<iostream>
    #include<vector>
    #include<utility>
    #include<algorithm>
    #include<queue>
    #include<set>
    #include<cassert>
    using namespace std;
    #define MAX 10000
    enum Color{white,gray,black};
    class Node{
    public:
        int index;
        Node* next=nullptr;//
        Node(int i):index(i){}
    };
    class VNode{
    public:
        char vertex;
        int index;
        int dist;
        int final;
        int indegree;
        Color color=white;
        int prev=-1;
        Node* firstNode=nullptr;
        VNode(char c,int i):vertex(c),index(i){}
    };
    typedef struct Graph{
        int EdgeNum;
        vector<VNode> Adj;
    }Graph;
    void FloydWarshall(Graph &G,int w[][6],int v[][6]){
        for(int k=0;k<6;k++){
            for(int i=0;i<6;i++){
                for(int j=0;j<6;j++){
                    if(w[i][j]>w[i][k]+w[k][j]){
                        w[i][j] = w[i][k]+w[k][j];
                        v[i][j] = k;                
                    }
                }
            }
        }
    }
    void AddEdge(Graph &G,int i,int j){
        Node* p = new Node(j);
        p->next = G.Adj[i].firstNode;
        G.Adj[i].firstNode = p;
    }
    void print_path(const Graph &G,int i,int j,const int v[][6]){
        if(v[i][j]==-1){
            cout<<G.Adj[i].vertex<<',';
        }
        else{
            print_path(G,i,v[i][j],v);
            print_path(G,v[i][j],j,v);
        }
    }
    int main(){
        Graph G;
        G.EdgeNum = 8;
        vector<char> v={'a','b','c','d','e','f'};
        for(int i=0;i<v.size();i++){
            G.Adj.push_back(VNode(v[i], i));
        }
        AddEdge(G,0,2);
        AddEdge(G,0,4);
        AddEdge(G,0,5);
        AddEdge(G,1,2);
        AddEdge(G,2,3);
        AddEdge(G,3,5);
        AddEdge(G,4,3);
        AddEdge(G,4,5);
        int w[6][6];
        for (int i = 0; i < 6; ++i)
        {
            for (int j = 0; j < 6; ++j)
            {
                if(i==j){
                    w[i][j]=0;
                }
                else{
                    w[i][j] = MAX;                
                }
            }
        }
        w[0][2] = 10;
        w[0][4] = 30;
        w[0][5] = 100;
        w[1][2] = 5;
        w[2][3] = 50;
        w[3][5] = 10;
        w[4][3] = 20;
        w[4][5] = 60;
        int path[6][6];
        for(int i=0;i<6;i++){
            for(int j=0;j<6;j++){
                path[i][j]=-1;
            }
        }
        FloydWarshall(G,w,path);
        for(int i=0;i<6;i++){
            for(int j=0;j<6;j++){
                if(w[i][j]!=MAX && i!=j){
                    cout<<'['<<i<<','<<j<<']'<<'	';
                    cout<<w[i][j]<<'	';
                    print_path(G,i,j,path);
                    cout<<G.Adj[j].vertex<<',';
                    cout<<endl;
                }    
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    般若与慈悲
    四谛
    Mysql:8.0.19:新特性、过期、已经删除的
    Mysql:As of 8.0.16:--validate-config:新增的服务器配置验证特效:good!
    Mysql:FIPS:Federal Information Processing Standards 140-2:世上有不透风的墙么?!
    ASP.NET Core WebApi使用Swagger生成API说明文档【xml注释版】
    ASP.NET Core WebApi使用Swagger生成API说明文档【特性版】
    Idea导入Eclipse的Web项目并部署到Tomcat
    在.Net中使用RedLock实现分布式锁
    【转】在C#中使用Json.Net进行序列化和反序列化及定制化
  • 原文地址:https://www.cnblogs.com/bukekangli/p/4394707.html
Copyright © 2011-2022 走看看