白书上的dijkstra+堆优化/dijkstra的一些性质

模板

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>

using namespace std;

const int maxn=11111;
const int maxm=11111;
const int INF=1e9;

struct Edge{
    int from,to,dist;
};

struct HeapNode{
    int d,u;
    bool operator<(const HeapNode& rhs) const{
        return d>rhs.d;
    }
};

struct Dijkstra{
    int n,m;
    vector<Edge> edges;
    vector<int> G[maxn];
    bool done[maxn];
    int d[maxn];
    int p[maxn];

    void init(int n){
        this->n=n;
        for (int i=0;i<n;i++) G[i].clear();
        edges.clear();
    }

    void addedge(int from,int to,int dist){
        edges.push_back((Edge){from,to,dist});
        m=edges.size();
        G[from].push_back(m-1);
    }

    void dijkstra(int s){
        priority_queue<HeapNode>que;
        for (int i=0;i<n;i++) d[i]=INF;
        d[s]=0;
        memset(done,0,sizeof(done));
        que.push((HeapNode){0,s});
        while (!que.empty()){
            HeapNode x=que.top();
            que.pop();
            int u=x.u;
            if (done[u]) continue;
            done[u]=true;
            for (int i=0;i<G[u].size();i++){
                Edge& e=edges[G[u][i]];
                if (d[e.to]>d[u]+e.dist){
                    d[e.to]=d[u]+e.dist;
                    p[e.to]=G[u][i];//p[e.to]=e.from;
                    que.push((HeapNode){d[e.to],e.to});
                }
            }
        }

    }
};


性质

路径统计

用dijkstra还可以枚举两点间的所有最短路,以及统计最短路的条数。枚举最短路的方法是这样的:先求出所有点到目标点的最短路长度d[i],然后从起点开始出发行走,但只沿着d[i]=d[j]+w(i,j)的边走。不难证明,如果一直顺着这样的边走,走到目标点时,走出的一定是最短路;反过来,只要有一次走的不是这样的边,走到目标点时,走出的一定不是最短路。有了这样的结论,计数也不是难事,令f[i]表示从i到目标点的最短路的条数,则f[i]=sum{ f[j] | f[i]=d[j]+w(i,j) },边界条件为终点的f值等于1。


最短路树

用dijkstra算法可以求出单源最短路树,方法是在发现d[i]+w(i,j)<d[j]时除了更新d[j]之外还要设置p[i]=j。这样,把p看成是父指针,则所有点形成了一棵树。这样,要从起点出发沿最短路走到任意其他点,只需要顺着树上的边走即可。前面的dijkstra算法的代码已经求出了p数组。





原文地址:https://www.cnblogs.com/cyendra/p/3226317.html