• 堆优化迪氏最短单源路径原理及C++实现


    时间复杂度

    O(ElogE),E是边数。适用与稀疏图。

    使用前提

    边的权为正。可以非连通,非连通的距离为-1。


    原理

    优选队列(小根堆)记录两个数据:当前点到源点距离,当前点。先处理距离小的点;如果距离相等,先处理谁都可以。可以用pair记录,不用重写小于。优先队列只记录如下情况的距离:
    一,{0,源点}。
    二,任意点的最短距离和可以直达的边。
    如果是有向图,则入队数量等于边数,计算出起点最短路径的那一轮。无向图,则翻倍。显然出队数量等于入队数量。优先队列入队和出队时间复杂度都是O(logn),故总时间复杂度为O(nlogn)。

    样例

     
    下表分析源点为0的处理过程。
            

    初始

    入队{0,0}

    出队{0,0}

    入队{1,1}

    0到源点的最短距离为0

    入队{4,2}

    出队{1,1}

    入队{2,0}

    入队{3,2}

    1到源点的最短距离为1

    入队{5,3}

    出队{2,0}

    0已经处理

    出队{3,2}

    入队{7,0}

    2到源点最短距离为3

    入队{5,1}

    入队{6,3}

    出队{4,2}

    2已经处理

    出队{5,1}

    1已经处理

    出队{5,3}

    … 3到源点的最短距离是5。


    核心代码


    非常的简洁。

    1. typedef pair<long long, int> PAIRLLI;
    2. class  CHeapDis
    3. {
    4. public:
    5.     CHeapDis(int n)
    6.     {
    7.         m_vDis.assign(n, -1);
    8.     }
    9.     void Cal( int start, const vectorint, int>>>& vNeiB)
    10.     {
    11.         std::priority_queue, greater> minHeap;
    12.         minHeap.emplace(0, start);
    13.         while (minHeap.size())
    14.         {
    15.             const long long llDist = minHeap.top().first;
    16.             const int iCur = minHeap.top().second;
    17.             minHeap.pop();
    18.             if (-1 != m_vDis[iCur])
    19.             {
    20.                 continue;
    21.             }
    22.             m_vDis[iCur] = llDist;
    23.             for (const auto& it : vNeiB[iCur])
    24.             {
    25.                 minHeap.emplace(llDist + it.second, it.first);
    26.             }
    27.         }
    28.     }
    29.     vector<long long> m_vDis;
    30. };

    测试用例

    #include
    #include
    #include
    #include
    using namespace std;

    class CDebugDis : public CHeapDis
    {
    public:
        using CHeapDis::CHeapDis;
        void Assert(const vector& vDis)
        {
            for (int i = 0; i < vDis.size(); i++)
            {
                assert(vDis[i] == m_vDis[i]);
            }
        }
    };

    struct CDebugParam
    {
        int n;
        vector>> edges;
        int s;
        vector dis;//答案
    };

    int main()
    {
        vector params = { {1,{{}},0,{0}},
            {2,{{}},0,{0,-1}},{2,{{{1,2}},{{0,2}}},0,{0,2} }
            ,{3,{{{1,4},{2,5}},{{0,4}},{{0,5}}},0,{0,4,5} }
            ,{3,{{{1,4},{2,8}},{{0,4},{2,3}},{{0,8},{1,3}}},0,{0,4,7} }
            ,{3,{{{1,4},{2,8}},{{0,4},{2,5}},{{0,8},{1,5}}},0,{0,4,8} }
            ,{4,{{{1,1},{2,4}},{{0,1},{2,2},{3,4}},{{0,4},{1,2},{3,3}},{{1,4},{2,3}}},0,{0,1,3,5}}
        };
        for (const auto& par : params)
        {
            CDebugDis n2Dis(par.n);
            n2Dis.Cal(par.s, par.edges);
            n2Dis.Assert(par.dis);
        }
    }

    相关下载

    源码及测试用例:

    https://download.csdn.net/download/he_zhidan/88390995

    https://img-blog.csdnimg.cn/ea2601b3918f4aef836b5fe30da2ebf7.gif#pic_center#pic_center

    其它

    视频课程

    如果你觉得复杂,想从简单的算法开始,可以学习我的视频课程。

    https://edu.csdn.net/course/detail/38771

    我的其它课程

    https://edu.csdn.net/lecturer/6176

    测试环境

    win7 VS2019 C++17 或Win10 VS2022 Ck++17

    相关下载

    算法精讲《闻缺陷则喜算法册》doc版

    https://download.csdn.net/download/he_zhidan/88348653

    作者人生格言

    有所得,以墨记之,故曰墨家

    闻缺陷则喜。问题发现得越早,越给老板省钱。

    算法是程序的灵魂

    https://img-blog.csdnimg.cn/f95ddae62a4e43a68295601c723f92fb.gif#pic_center

  • 相关阅读:
    使用 rollup 打包一个原生 js + canvas 实现的移动端手势解锁功能组件
    centos7 安装 superset 2.0 并安装 pg mysql等驱动
    (续)SSM整合之springmvc笔记(SpringMVC处理ajax请求)(P154-158)
    K8s学习笔记——认识理解篇
    解决 idea maven依赖引入失效,无法正常导入依赖问题
    SNETCracker--超级弱口令检查工具简介
    centos7或centos8 chkconfig命令详解
    git 合并两个不同仓库
    C++初探 5-2(while循环 do while循环 输入 二维数组)
    实验六 并行口8255的使用—LED静态显示
  • 原文地址:https://blog.csdn.net/he_zhidan/article/details/133513907