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. Input 输入框

    Input 输入框 通过鼠标或键盘输入字符 <el-input v-model="input" placeholder="请输入内容"></e ...

  2. 第五周作业,LVM和TCP

    1.磁盘lvm管理,完成下面要求,并写出详细过程: 1) 创建一个至少有两个PV组成的大小为20G的名为testvg的VG;要求PE大小 为16MB, 而后在卷组中创建大小为5G的逻辑卷testlv; ...

  3. Selenium 2自动化测试实战20(操作cookie)

    一.操作cookie 有时候我们需要验证浏览器中cookie是否正确,因为基于真实cookie的测试是无法通过白盒和集成测试的.WebDriver提供了操作Cookie的相关方法,可以读取.添加和删除 ...

  4. javascript-->getElementsByClass

        //通过类名获取元素    //obj->目标元素的上一层元素  cName->目标类名 tagName->目标的标签类型(可缺省)    function getEleme ...

  5. java:LeakFilling(Servlet,JSP)

    1.web-inf中的  .jsp 文件不会运行,其他都根据web.xml文档中的自然顺序进行运行 2.keep-alive 长连接(持续)  UDP,TCP短连接 3.状态码:1(消息异常) 2(成 ...

  6. python学习之socket&黏包

    7.4 socket ​ [重要] 避免学习各层的接口,以及协议的使用, socket已经封装好了所有的接口,直接使用这些接口或者方法即可,方便快捷,提升开发效率. socket在python中就是一 ...

  7. python学习之网络基础

    七 网络编程 7.1 C/S B/S架构 7.1.1 认识 Client : 客户端 Browser :浏览器 Server :服务器端 C/S:客户端与服务器之间的构架 B/S:浏览器与服务器之间的 ...

  8. neo4j - 查询效率的几种优化思路

    最近在公司实习做的就是优化neo4j图形数据库查询效率的事,公司提供的是一个在Linux上搭建且拥有几亿个节点的数据库.开始一段时间主要是熟悉该数据库的一些基本操作,直到上周才正式开始步入了优化数据库 ...

  9. Python 对于分表的操作

    在操作数据库的业务里,我们系统采用了orm框架 ,避免了过多的写sql,利用实体对数据库进行操作 需求: 账户系统里的account表是进行了分表,分表规则为accountid进行20取模,测试环境分 ...

  10. Java初始和环境搭建

    前世今生 Java语言是什么? 一种计算机编程语言.名字取自咖啡. Java语言发展简史 Java语言之父:James Gosling SUN(Stanford University Network ...