• Dijkstra


    Dijkstra

    前言

    总感觉最近几天自己摸鱼摸得有点厉害,整个人都不再状态。

    今天好不容易下定决心一定要把(Dijkstra)整理出来,因为这个工作自己已经鸽了好几天了,实在无法忍受他继续呆在我的脑子里面碍事,于是今天决定对他下手。

    好嘛~

    爷来了~

    蛋是……

    当然了,有一个小小的问题:

    就是,我,其实还是并不太会写(DJ)的代码,

    但是在经历了为无数题解的洗礼之后,我已经完全明白,(DJ)的是思路了。

    什么是(Djikstra)

    借用洛谷中某一篇题解的介绍:

    (Dijkstra)是一种单源最短路径算法,时间复杂度的上限为(O)(n^2))(朴素),在实际应用中较为稳定;加上堆优化之后更是具有(O)(((m+n)(log_2n))的时间复杂度,在稠密图中有不俗的表现。

    啊吧啊吧……在线吃瓜。

    (Djikstra)的使用说明

    产品名称:(Djikstra)

    使用限制:仅限于无负边权的图

    原因:你见过那个说明书告诉你原因?所以……没有

    使用方法:口服

    啊不是不是,其实呢……(Dijkstra)的本质上的思想就是贪心(毕竟最短路问题是完全可以贪心的)

    使用(Dijkstra)其实非常简单,其实就是初始化一个点。

    使他的(dis)[(start)]=0,然后把其他所有结点的(dis)[(i)]设为无穷大。

    然后从(start)开始向所能到达的点进行遍历。

    寻找所需要消耗的边权最少的一条边,然后更新所到达的点的点权为(dis[start]+w[i]),(w[i])表示的是边权。

    然后从刚才更新的那个点开始重复操作。

    但是在后续的操作之中需要注意比较更新之后的点的权值和点原来的权值,如果大于就不能更新。

    至于为什么不再上面写呢……

    一是因为我忘了,

    而是因为上面已经设成了(MAX)

    显然不可能出现更大的权了,

    必然更新。

    (Dijkstra)为什么是正确的

    依然借用题目。

    其实意思就是我们要证明(Dijkstra)的正确性。

    其实很简单,甚至有些显而易见。

    当所有的边权都是正的的时候,无论怎么相加,必然你能够更新出最小的点权,从而实现从某一个点出发到达其余所有的点的单源最短路径。

    没有图解

    (Dijkstra)的堆优化

    众所周知,在(Dijkstra)的每一步操作之中,都需要找到当前所在点所连通的边的边权最小的一条。

    所以,

    自然而然地,

    想到了堆!

    我们可以使用堆对(dis)数组进行维护,用(O(log_2n))的时间取出堆顶元素并删除,用(O(log_2n))的时间遍历每条边,总复杂度为(O((m+n)log_2n))

    范例代码

    本来是没有的,但是怕有人打我,于是从洛谷(copy)了一份

    致敬原作者:

    little_sun

    感谢代码:

    #include<bits/stdc++.h>
    
    const int MaxN = 100010, MaxM = 500010;
    
    struct edge
    {
        int to, dis, next;
    };
    
    edge e[MaxM];
    int head[MaxN], dis[MaxN], cnt;
    bool vis[MaxN];
    int n, m, s;
    
    inline void add_edge( int u, int v, int d )
    {
        cnt++;
        e[cnt].dis = d;
        e[cnt].to = v;
        e[cnt].next = head[u];
        head[u] = cnt;
    }
    
    struct node
    {
        int dis;
        int pos;
        bool operator <( const node &x )const
        {
            return x.dis < dis;
        }
    };
    
    std::priority_queue<node> q;
    
    
    inline void dijkstra()
    {
        dis[s] = 0;
        q.push( ( node ){0, s} );
        while( !q.empty() )
        {
            node tmp = q.top();
            q.pop();
            int x = tmp.pos, d = tmp.dis;
            if( vis[x] )
                continue;
            vis[x] = 1;
            for( int i = head[x]; i; i = e[i].next )
            {
                int y = e[i].to;
                if( dis[y] > dis[x] + e[i].dis )
                {
                    dis[y] = dis[x] + e[i].dis;
                    if( !vis[y] )
                    {
                        q.push( ( node ){dis[y], y} );
                    }
                }
            }
        }
    }
    
    
    int main()
    {
        scanf( "%d%d%d", &n, &m, &s );
        for(int i = 1; i <= n; ++i)dis[i] = 0x7fffffff;
        for( register int i = 0; i < m; ++i )
        {
            register int u, v, d;
            scanf( "%d%d%d", &u, &v, &d );
            add_edge( u, v, d );
        }
        dijkstra();
        for( int i = 1; i <= n; i++ )
            printf( "%d ", dis[i] );
        return 0;
    }
    

    此致,

    敬礼!

  • 相关阅读:
    Eclipse+Maven整合开发Java项目(二)➣webapp3.0以上的Maven项目
    Eclipse+Maven整合开发Java项目(一)➣Maven基础环境配置
    JAVA-ORM框架整理➣Mybatis操作MySQL
    Spring MVC基础知识整理➣Spring+SpringMVC+Hibernate整合操作数据库
    Spring MVC基础知识整理➣拦截器和自定义注解
    Spring MVC基础知识整理➣国际化和异常处理
    Spring MVC基础知识整理➣数据校验与格式化
    Spring MVC基础知识整理➣View与Controller数据交互
    面向过程,面向对象,函数式对同一个问题的思考方式
    分享一个简单程序(webApi+castle+Automapper+Ef+angular)
  • 原文地址:https://www.cnblogs.com/JingFenHuanZhe/p/Dijkstra0922.html
Copyright © 2020-2023  润新知