1.题目

分析与解题思路

dijkstra算法是典型的用来解决单源最短路径的算法,该算法采用贪心的思想,广度优先搜索的策略,每一轮从当前节点找对与其邻接的所有节点进行放松操作(比较距离源点的距离,来决定是否执行),记录当前节点为已访问,之后从所有未访问过的节点中找到距离源点最近的节点作为当前节点,重复上述操作。BFS策略体现在每次从当前节点,访问所有与其邻接的节点;贪心的思想体现在,每一轮之后,当前距离最短的点S被认为不存在从源点到S更短的路径,每次当通过S对与其邻接的节点进行放松后,可以将S从集合剔除,因为通过后续的到达S节点的距离一定更长。

证明:

假设源点为S0,当前节点为S,节点S0到节点u的距离为dis[u];

因为当前节点为S,说明其他节点u!=S,必有dis[u]>dis[S]

假如后续的节点v有一条到S的路径,源点到v的距离必然是通过S或者u进行放松的

dis[v]>=min{dis[u],dis[S]}

另外dijkstra算法只能解决权值为正的情况,当存在负权值时,算法可能出错,比如:

节点从1开始,根据贪心思想,下一下节点应该选择3,记录dis[3]=2

但是有更短的路径1->2->3 距离为1

测试用例

(测试用例1)

(测试用例2)

输入说明:

第一行:测试用例的数目

对于每一个测试用例,第一行,n,m,s;n代码节点的个数,m代表边的条数,s代码源节点

后面m行,u,v,w代表一条u->v权值为w的边

程序实现

 public List<int[]>dijkstra1(int s);使用的是课本上比较朴素的实现方法。

下面是我自己的实现方法:

//采用优先队列优化

   public List<int[]>dijkstra2(int s){

        int[]path=new int[n+1];

        int[]dis=new int[n+1];

        boolean[]mark=new boolean[n+1];

        Arrays.fill(dis, INF);

        dis[s]=0;

        path[s]=0;

        PriorityQueue pq=new PriorityQueue(n);

        for(int i=1;i<n;++i) {

            for(Node temp:table.get(s)) {

                if(!mark[temp.index]&&dis[s]+temp.weight<dis[temp.index]) {

                    if(dis[temp.index]==INF) {

                        dis[temp.index]=dis[s]+temp.weight;

                        pq.offer(temp.index, dis[temp.index]);

                    }else {

                        pq.increase(temp.index, dis[s]+temp.weight-dis[temp.index]);

                        dis[temp.index]=dis[s]+temp.weight;

                    }

                    path[temp.index]=s;

                }

            }

            mark[s]=true;

            s=pq.poll();

        }

        ArrayList<int[]>res=new ArrayList<int[]>(2);

        res.add(path);

        res.add(dis);

        return res;

    }

使用优先队列优化,每次寻找最小的距离的节点的时候就不用线性遍历整个表,可以在logV的时间复杂度内获得最小距离的节点;同时我在使用优先队列的时候,我的实现方式对优先队列有以下额外要求:(优先队列的代码有点长,具体情况源代码)

1) 能够更新元素

先找到指定的元素,根据2)中的方法,然后更新dis,如果dis变小进行上滤,dis变大进行下滤。

2) 能够在常数时间内找到在图中某个标号的节点在优先队列中的位置

一个很常见的思路就是使用空间换时间,使用一个数组保存Node在优先队列中的位置,并且在优先队列进行插入,删除,更新时也要同步更新。

运行截图

结论

朴素的实现时间复杂度是O(E*V)(我使用的是邻接表存储图),使用优先队列优化时间复杂度为O(VlogV);关于图的存储,稀疏图使用邻接表占用内存比较少,稠密图适合用邻接矩阵,访问速度很快。

dijkstra算法之优先队列优化的更多相关文章

  1. dijkstra算法与优先队列

    这是鄙人的第一篇技术博客,作为算法小菜鸟外加轻度写作障碍者,写技术博客也算是对自己的一种挑战和鞭策吧~ 言归正传,什么是dijkstra算法呢? -dijkstra算法是一种解决最短路径问题的简单有效 ...

  2. dijkstra算法的堆优化

    普通的dijkstra算法模板: //数据结构 int g[LEN][LEN]; //邻接矩阵 int vis[LEN]; //标记是否访问 int dist[LEN] //源点到各点的距离 fill ...

  3. 单源最短路径:Dijkstra算法(堆优化)

    前言:趁着对Dijkstra还有点印象,赶快写一篇笔记. 注意:本文章面向已有Dijkstra算法基础的童鞋. 简介 单源最短路径,在我的理解里就是求从一个源点(起点)到其它点的最短路径的长度. 当然 ...

  4. Dijkstra普通算法及优先队列优化

    #include<stdio.h> #include<iostream> #define maxv 100 #define inf 0x3fffffff using names ...

  5. 单源最短路-dijkstra算法(未优化)

    bool used[maxn]; int g[maxn][maxn]; // 边未联系的填充为INF int d[maxn]; void dijkstra(int s){ memset(g,false ...

  6. 【Luogu P4779】dijkstra算法的堆优化

    Luogu P4779 利用堆/优先队列快速取得权值最小的点. 在稠密图中的表现比SPFA要优秀. #include<iostream> #include<cstdio> #i ...

  7. 基于STL优先队列和邻接表的dijkstra算法

    首先说下STL优先队列的局限性,那就是只提供入队.出队.取得队首元素的值的功能,而dijkstra算法的堆优化需要能够随机访问队列中某个节点(来更新源点节点的最短距离). 看似可以用vector配合m ...

  8. POJ 3268 Silver Cow Party 最短路—dijkstra算法的优化。

    POJ 3268 Silver Cow Party Description One cow from each of N farms (1 ≤ N ≤ 1000) conveniently numbe ...

  9. Dijkstra算法优先队列实现与Bellman_Ford队列实现的理解

    /* Dijkstra算法用优先队列来实现,实现了每一条边最多遍历一次. 要知道,我们从队列头部找到的都是到 已经"建好树"的最短距离以及该节点编号, 并由该节点去更新 树根 到其 ...

随机推荐

  1. nodejs之静态文件托管、 路 由、EJS 模板引擎、GET、POST

    1.静态文件托管 静态文件托管:是指对于一个js方法进行封装,提高代码可读性 //fs模块 var fs=require('fs'); //path模块 var path=require('path' ...

  2. surface book2 添加自定义分辨率

    surface book2 13.5英寸  是3:2的屏幕, 因为默认分辨率3000*2000实在是太高了,看字的时候眼睛有点吃不消  即使开启windows的自定义缩放也有点难受,加上windows ...

  3. Java基础之Volatile原理

    原文链接: http://www.aoaoyi.com/archives/956.html 计算机在执行程序时,每条指令都是在CPU中执行的,而执行指令过程中,势必涉及到数据 的读取和写入.由于程序运 ...

  4. jquery实现分页效果

    通过jq实现分页的原理如下:将所有条数加载到页面中,根据每页放特定条数(例如 5 条)获取jquery对象索引,使部分条数显示,其他条数隐藏. 前提:引入jquery.js 代码 <!DOCTY ...

  5. firewalld防火墙简介

    1.防火墙 防火墙,其实就是一个隔离工具:工作于主机或者网络的边缘 对于进出本主机或者网络的报文根据事先定义好的网络规则做匹配检测, 对于能够被规则所匹配的报文做出相应处理的组件(这个组件可以是硬件, ...

  6. 【CUDA开发】CUDA从入门到精通

    CUDA从入门到精通(零):写在前面 在老板的要求下,本博主从2012年上高性能计算课程开始接触CUDA编程,随后将该技术应用到了实际项目中,使处理程序加速超过1K,可见基于图形显示器的并行计算对于追 ...

  7. vue--键盘修饰符以及自定义键盘修饰符

    键盘修饰符以及自定义键盘修饰符 1.vue键盘修饰符[了解即可] ​地址:https://cn.vuejs.org/v2/guide/events.html#%E6%8C%89%E9%94%AE%E4 ...

  8. Neo4j下载与使用

    Neo4j 官网 : https://neo4j.com/ Neo4j 国内: http://neo4j.com.cn/topic/5b003eae9662eee704f31cee http://we ...

  9. 2017 ACM-ICPC 亚洲区(乌鲁木齐赛区)网络赛 F. Islands

    On the mysterious continent of Tamriel, there is a great empire founded by human. To develope the tr ...

  10. webpack入门学习手记(一)

    本人微信公众号:前端修炼之路,欢迎关注. 之前用过gulp.grunt,但是一直没有学习过webpack.这两天刚好有时间,学习了下webpack.webpack要想深入研究,配置的东西比较多,网上的 ...