Dijkstra

  • 单源最短路:起点到其余点的最短路

  • 多源最短路:每一对顶点间的最短路

Dijkstra(单源最短路,无负环)

Dijkstra的本质为BFS+贪心

算法流程:设标记数组 S S S作为点集(标记已确定最短路的点集),源点到每个顶点的最短路长度 d i s dis dis(初始化为 + ∞ +\infty +表示该点不可达),路径数组 p a t h path path(存储其上一个来源顶点,初始化为 − 1 -1 1表示无路径)

循环执行下列步骤,直到点集 S S S中所有顶点全部被标记或者所有顶点的 d i s dis dis值都无法再更新:

  1. 选取最小顶点(贪心):从点集 S S S中找出未被标记且 d i s dis dis最小的顶点 w o r k work work(首次即为源点)
  2. 松弛入度边(BFS扩散):考查顶点 w o r k work work(将其在 S S S中标记),访问与 w o r k work work直接邻接且先前未被考查所标记的顶点 n e w new new,检查其是否能通过 w o r k work work作为其中转点而使其 d i s dis dis更短(松弛入度边)。设 w o r k work work n e w new new间的权值为 w w w,则 d i s [ n e w ] = m i n ( d i s [ n e w ] , d i s [ w o r k ] + w ) dis[new]=min(dis[new],dis[work]+w) dis[new]=min(dis[new],dis[work]+w)
  3. 更新最短路径:若 d i s [ n e w ] dis[new] dis[new]被更新(入度边被松弛),则将 p a t h [ n e w ] path[new] path[new]修改为 w o r k work work

  1. 一旦顶点被加入到已选点集 S S S中,其将不再被考查,最短路长度 d i s dis dis将不再改变。因此,Dijkstra不能用于求解含有负权的图。
  2. Dijkstra不能求最长路

朴素版Dijkstra( O ( V 2 ) O(V^2) O(V2))

using ll=long long;
const ll INF=__LONG_LONG_MAX__;
ll n,m,s;//点数,边数,源点
struct vertex{
    int e=-1;
}v[n];
struct edge{
    int f,t,w,n=-1;
}e[m];
vector<bool>S;//只定义已选集合即可
vector<ll>dis,path;
void dijkstra(){
    dis.resize(n,INF),path.resize(n,-1),S.resize(n);
    dis[s]=0;//源点到自己距离为0
    for(ll j=0;j<n;j++){//尽可能使未选点集添加到已选点集
        ll minn=INF,i=-1;
        for(ll k=0;k<n;k++){
            if(!S[k]&&dis[k]!=INF&&dis[k]<minn){//贪心,从未选点集中选最小的
                i=k;
                minn=dis[k];
            }
        }
        if(i==-1) break;//剩余点均不可达
        S[i]=1;//将最小点加入已选集合中
        for(ll work=v[i].e;work!=-1;work=e[work].n){//考查最小点,BFS扩散其邻接点
            if(!S[e[work].t]&&e[work].w!=INF&&dis[e[work].t]>dis[i]+e[work].w){//松弛入度边
                dis[e[work].t]=dis[i]+e[work].w;
                path[e[work].t]=i;
            }
        }
    }
}

堆优化的Dijkstra( O ( V log ⁡ 2 V ) O(V\log_2V) O(Vlog2V))

堆优化的Dijkstra为BFS+优先队列,另设小根堆 Q Q Q动态维护最小边。

using ll=long long;
using pll=pair<ll,ll>;//first存点 second存最短距离
const ll INF=__LONG_LONG_MAX__;
struct vertex{
    ll e=-1;
}v[MAXV];
struct edge{
    ll f,t,w,n=-1;
}e[MAXE];
ll n,m,s;//点数 边数 源点
vector<bool>S;
vector<ll>dis,path;
bool cmp(pll a,pll b){//小根堆比较函数
    return a.second>b.second;
}
priority_queue<pii,vector<pii>,bool(*)(pll,pll)>pq(cmp);//构造小根堆
void dijkstra(){
    S.resize(n),dis.resize(n,INF),path.resize(n,-1);
    dis[s]=0;
    pq.push(make_pair(s,dis[s]));
    while(pq.size()){
        if(S[pq.top().first]){
            pq.pop();
            continue;
        }
        S[pq.top().first]=1;
        for(ll work=v[pq.top().first].e;work!=-1;work=e[work].n){//考查work,BFS扩散其邻接点
            if(!S[e[work].t]&&e[work].w!=INF&&dis[e[work].t]>pq.top().second+e[work].w){//松弛入度边
                dis[e[work].t]=pq.top().second+e[work].w;
                path[e[work].t]=pq.top().first;
                pq.push(make_pair(e[work].t,dis[e[work].t]));
            }
        }
        pq.pop();
    }
}

相关推荐

  1. Dijkstra

    2024-07-22 03:44:02       24 阅读
  2. Dijkstra&floyed

    2024-07-22 03:44:02       47 阅读
  3. Dijkstra算法

    2024-07-22 03:44:02       39 阅读
  4. dijkstra和prim算法

    2024-07-22 03:44:02       60 阅读
  5. 最短路径 Dijkstra

    2024-07-22 03:44:02       57 阅读
  6. Dijkstra算法的原理

    2024-07-22 03:44:02       34 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-22 03:44:02       104 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-22 03:44:02       115 阅读
  3. 在Django里面运行非项目文件

    2024-07-22 03:44:02       94 阅读
  4. Python语言-面向对象

    2024-07-22 03:44:02       100 阅读

热门阅读

  1. B树:高效的数据存储结构

    2024-07-22 03:44:02       23 阅读
  2. newton算法实现的div的verilog

    2024-07-22 03:44:02       21 阅读
  3. Servlet会话跟踪基础

    2024-07-22 03:44:02       22 阅读
  4. 实变函数精解【6】

    2024-07-22 03:44:02       22 阅读
  5. springSecurity学习之springSecurity流程

    2024-07-22 03:44:02       21 阅读
  6. Symfony表单系统详解:构建强大且灵活的表单

    2024-07-22 03:44:02       23 阅读