介绍

Bellman-Ford算法能在更普遍的情况下(存在负权边)解决单源点最短路径问题,但是对于DAG,可以有更加简化的算法去计算,使得时间复杂度更低。
针对DAG的特点,以拓扑排序为基础,提出了解决DAG的最短路径问题的简单算法。通过理论分析,表明该算法具有理想的运算效率,其中,解决单源点问题的运算时间与E成正比,解决所有点对问题的运算时间与VE成正比。拓扑排序策略对于此类最短路径问题的研究,较传统的方法运算简单、求解直观。

适用条件&范围

1.单源最短路径(从源点s到其它所有顶点v);
2.有向无环图(DAG)
3.边权可正可负;

算法描述

(1)初始化,入度为0的节点d为0,其他的节点d值为INF。

(2)对DAG进行拓扑排序,得到拓扑序列。

(3)按照拓扑序列遍历DAG的点,进行松弛操作,对于每个点u,遍历其所有的出边<u,v>,如果d[v] > d[v] + length<u,v>,则更新。

时间复杂度

算法时间复杂度O(V+E)。

Java代码实现

package algorithms;import util.AlgoGraph;/*** Created with IntelliJ IDEA.* Created by The_Sam on 2017/5/8 22:08*/
public class DAG extends ShortestAlgorithms {public static void main(String[] args) {ShortestAlgorithms dag = new DAG();System.out.println(dag.analyse(AlgoGraph.defaultMap3()));}boolean analyse(AlgoGraph algoGraph) {dis = new int[algoGraph.getNodenum()];//dis[i] 为 i点到s的最短距离pre = new int[algoGraph.getNodenum()];//pre[i] 为i搭配s的最短距离的上一个节点ini(algoGraph, algoGraph.getNodenum());int vertexs[] = topSort(algoGraph);relex(algoGraph, algoGraph.getNodenum(), algoGraph.getEdgenum(), vertexs);return true;}void ini(AlgoGraph algoGraph, int nodenum) {//初始化,将dis[s]设为0,其他的都设为无限大int s = algoGraph.getOriginal();//原点for (int i = 0; i < nodenum; i++) {dis[i] = i == s ? 0 : MAXN;}}void relex(AlgoGraph algoGraph, int nodenum, int edgenum, int vertexs[]) {//松弛操作,遍历每条边nodenum次,找到所有节点的对应dis和pre// 实际上就是暴力检测有没有更短的路径for (int i = 0; i < nodenum; i++) {for (int j = 0; j < edgenum; j++) {int v = algoGraph.edge.get(j).v;if (v != vertexs[i]) continue;//对拓扑排序从前往后操作,省去后面很多多余的操作int u = algoGraph.edge.get(j).u;int cost = algoGraph.edge.get(j).cost;if (dis[v] > dis[u] + cost) {dis[v] = dis[u] + cost;pre[v] = u;}}}}/*** @Description : 拓扑排序* @Author : The_Sam* @Datetime : 2017/5/8 23:22* @Params : AlgoGraph algoGraph* @Return : int[]*/int[] topSort(AlgoGraph algoGraph) {int nodeNum = algoGraph.getNodenum();int result[] = new int[nodeNum];int indegrees[] = algoGraph.getIndegrees();for (int cnt = 0; cnt < nodeNum; ) {for (int i = 0; i < nodeNum; i++) {if (indegrees[i] == 0) result[cnt++] = i;if (indegrees[i] >= 0) indegrees[i]--;}}return result;}}
AlgoGraph.java 表示图的代码附上
package util;import lombok.Getter;
import lombok.Setter;import java.util.ArrayList;/*** Created by The_Sam on 2017/5/8.* 图是从0到nodenum-1表示相应节点*/
public class AlgoGraph {@Getter@Setterprivate int original;@Getter@Setterprivate int nodenum;private int indegrees[];//    private int indegrees[];//indegree[i]表示i节点的入度public ArrayList<AlgoEdge> edge;public int getEdgenum() {return edge.size();}public AlgoGraph(int original, int nodenum, ArrayList<AlgoEdge> edge) {this.original = original;this.nodenum = nodenum;this.edge = edge;}/*** @Description :返回函数各个节点的入度* @Author : The_Sam* @Datetime : 2017/5/8 23:04* @Params :* @Return : int[]*/public int[] getIndegrees() {indegrees=new int[nodenum];for (AlgoEdge e :edge) {indegrees[e.v]++;}return indegrees;}/*** @Description: 返回一个图,为算法导论图24-4,带负权无负权回路有向环图* @Author: The_Sam* @Datetime: 2017/5/8 21:22* @Params: []* @Return: AlgoGraph*/static public AlgoGraph defaultMap1() {ArrayList<AlgoEdge> edge = new ArrayList<AlgoEdge>();edge.add(new AlgoEdge(0, 1, 6));edge.add(new AlgoEdge(0, 2, 7));edge.add(new AlgoEdge(1, 2, 8));edge.add(new AlgoEdge(1, 3, 5));edge.add(new AlgoEdge(1, 4, -4));edge.add(new AlgoEdge(2, 3, -3));edge.add(new AlgoEdge(2, 4, 9));edge.add(new AlgoEdge(3, 1, -2));edge.add(new AlgoEdge(4, 0, 2));edge.add(new AlgoEdge(4, 3, 7));int original = 0;int nodenum = 5;return new AlgoGraph(original, nodenum, edge);}/*** @Description: 返回一个图,为算法导论图24-4改变版,有负权回路有向环图* @Author: The_Sam* @Datetime: 2017/5/8 21:22* @Params: []* @Return: AlgoGraph*/static public AlgoGraph defaultMap2() {ArrayList<AlgoEdge> edge = new ArrayList<AlgoEdge>();edge.add(new AlgoEdge(0, 1, 6));edge.add(new AlgoEdge(0, 2, 7));edge.add(new AlgoEdge(1, 2, 8));edge.add(new AlgoEdge(1, 3, 5));edge.add(new AlgoEdge(1, 4, -4));edge.add(new AlgoEdge(2, 3, -3));edge.add(new AlgoEdge(2, 4, 9));edge.add(new AlgoEdge(3, 1, -2));edge.add(new AlgoEdge(4, 0, 2));edge.add(new AlgoEdge(4, 3, 5));//此处改变 edge.add(new AlgoEdge(4, 3, 7));int original = 0;int nodenum = 5;return new AlgoGraph(original, nodenum, edge);}/*** @Description: 返回一个图,为算法导论图24-4改变版,有向无环图* @Author: The_Sam* @Datetime: 2017/5/8 21:22* @Params: []* @Return: AlgoGraph*/static public AlgoGraph defaultMap3() {ArrayList<AlgoEdge> edge = new ArrayList<AlgoEdge>();edge.add(new AlgoEdge(0, 1, 6));edge.add(new AlgoEdge(0, 2, 7));edge.add(new AlgoEdge(1, 2, 8));edge.add(new AlgoEdge(1, 3, 5));edge.add(new AlgoEdge(1, 4, -4));edge.add(new AlgoEdge(2, 3, -3));edge.add(new AlgoEdge(2, 4, 9));//edge.add(new AlgoEdge(3, 1, -2));//edge.add(new AlgoEdge(4, 0, 2));//edge.add(new AlgoEdge(4, 3, 5));//此处改变 edge.add(new AlgoEdge(4, 3, 7));int original = 0;int nodenum = 5;return new AlgoGraph(original, nodenum, edge);}/*** @Description: 返回一个图,为算法导论图24-4改变版,无负权有向环图* @Author: The_Sam* @Datetime: 2017/5/8 21:22* @Params: []* @Return: AlgoGraph*/static public AlgoGraph defaultMap4() {ArrayList<AlgoEdge> edge = new ArrayList<AlgoEdge>();edge.add(new AlgoEdge(0, 1, 6));edge.add(new AlgoEdge(0, 2, 7));edge.add(new AlgoEdge(1, 2, 8));edge.add(new AlgoEdge(1, 3, 5));edge.add(new AlgoEdge(1, 4, 4));edge.add(new AlgoEdge(2, 3, 3));edge.add(new AlgoEdge(2, 4, 9));//edge.add(new AlgoEdge(3, 1, -2));//edge.add(new AlgoEdge(4, 0, 2));//edge.add(new AlgoEdge(4, 3, 5));//此处改变 edge.add(new AlgoEdge(4, 3, 7));int original = 0;int nodenum = 5;return new AlgoGraph(original, nodenum, edge);}
}
AlgoEdge.java表示边的代码附上
package util;/*** Created by The_Sam on 2017/5/8.*/
public class AlgoEdge {public int u,v;public int cost;public AlgoEdge(int u, int v, int cost) {this.u = u;this.v = v;this.cost = cost;}
}
												

算法导论——24.2 DAG最短路径算法java实现相关推荐

  1. 算法导论之单源最短路径

    单源最短路径,在现实中是很多应用的,是图的经典应用,比如在地图中找出两个点之间的最短距离.最小运费等.单源最短路径的问题:已知图G=(V,E),找出给定源顶点s∈V到每个顶点v∈V的最短路径.单源最短 ...

  2. 算法导论之图的基本算法

    图是一种数据结构,有关图的算法是计算机科学中基础性的算法.这个论述恰如其分. 图的基本算法包括图的表示方法和图的搜索方法.图的搜索技术是图算法领域的核心,有序地沿着图的边访问所有顶点,可以发现图的结构 ...

  3. 算法导论 pdf_学习数据结构和算法最好的书是什么?

    ----------- 通知:如果本站对你学习算法有帮助,请收藏网址,并推荐给你的朋友.由于 labuladong 的算法套路太火,很多人直接拿我的 GitHub 文章去开付费专栏,价格还不便宜.我这 ...

  4. 算法导论中C语言代码,算法导论-学习笔记与进度

    算法导论 阅读进度 第一部分 基础知识 第一章 计算中算法的角色 Done 1.1 算法 输入与输出 算法可以解决哪些问题 数据结构 技术 一些比较难的问题 1.2 作为一种技术的算法 效率 算法和其 ...

  5. 算法导论-上课笔记7:贪心算法

    文章目录 0 前言 1 活动选择问题 1.1 活动选择问题的最优子结构 1.2 贪心选择 1.3 递归贪心算法 1.4 迭代贪心算法 2 贪心算法原理 2.1 贪心选择性质 2.2 最优子结构 2.3 ...

  6. 算法导论——所有点对最短路径:稀疏图Johnson算法

    2019独角兽企业重金招聘Python工程师标准>>> package org.loda.graph;import org.loda.structure.Stack; import ...

  7. 算法导论之有关数论的算法

    关于数论,想到的就是密码系统和大素数.大素数的易求和因子分解的高难度是密码系统安全性的数学基础.输入一个大的整数,用位操作次数来衡量数论算法的时间性能. 1)初等数论概念 关于整数集合Z={-,-2, ...

  8. 【转】算法导论学习笔记 一 分治算法

    分治策略是一种常见的算法.在分治策略中,我们递归的求解一个问题,在每层递归中应用如下三个步骤: 1. 分解,将问题分解成规模更小但解决方案相同的子问题 2. 解决,递归的求解子问题,如果子问题足够小则 ...

  9. 《算法导论3rd第一章》算法在计算中的作用

    前言 什么是算法?为什么算法值得研究?算法的作用是什么 算法 算法就是任何良定义的计算过程,该过程取某个值或值的集合作为输入并产生某个值或值的集合做为输出.即就是把输入转换成输出的计算步骤的一个序列. ...

最新文章

  1. 网络营销专员浅析企业网站网络营销的多个优势!
  2. FreeMarker 语法 include 引用模板
  3. PMCAFF | 史上最完整的沙龙活动策划总结
  4. php调用matlab
  5. JSP 中使用Struts2的值
  6. CF1628A-Meximum Array【二分】
  7. oracle us7ascii 中文,US7ASCII字符集中汉字显示问题
  8. 全面介绍Windows内存管理机制及C++内存分配实例(五):堆
  9. 为什么我不推荐你使用vue-cli创建脚手架?
  10. 组合日期_为什么我的透视表没法按日期组合?
  11. Linux下C++静态库、动态库的制作与使用
  12. Vmware中RedHat命令行和图形界面切换
  13. 移动安全工具:fastboot
  14. XML约束、如何在xml中引入dtd、dtd语法、ENTITY(实体)
  15. MYSQL判断中文、英文、日文常用语句
  16. Alertmanager 告警详解
  17. HTML5和CSS3的一些小总结
  18. 菌群最新资讯热评 | 菌群与癌症免疫疗法,菌群与消毒剂
  19. win7计算机任务栏颜色怎么,如何修改win7电脑下方任务栏的颜色?
  20. jstree中文github文档

热门文章

  1. JAVA Applet版的连连看游戏
  2. 四天搞懂生成对抗网络(一)——通俗理解经典GAN
  3. 【前端测试与集成】使用mocha和sinon进行单元测试
  4. 简述——什么是软件质量的六大特性?
  5. 夹治具设计需要遵循的一些设计准则:
  6. 【论文阅读】RAPTOR: Robust and Perception-Aware Trajectory Replanning for Quadrotor Fast Flight
  7. 开源 制作磁力链接_3个开源链接缩短器
  8. IMX6ULL裸机开发之点亮LED灯
  9. 分式怎么开根号_怎么打出根号二(教你如何写出√2的连分式)
  10. 如何有效地阅读技术书籍