算法导论——有向无环加权图的最短路径

package org.loda.graph;

import org.loda.structure.Stack;
import org.loda.util.In;

/**
 *
 * @ClassName: NoCycleSP
 * @Description: 有向无环图的最短路径算法
 *
 * 无环图可以采用拓扑排序来处理,进行拓扑排序中不会有排名靠后的指向排名靠前的情况,所以拓扑排序的第一个节点是无法从其他节点抵达的
 *
 * 无环权重有向图的算法时间复杂度可以高达O(V+E),比Dijkstra算法更好,并且能解决负数权重问题,不过他需要有向图是无环的
 *
 * @author minjun
 * @date 2015年5月28日 上午9:47:26
 *
 */
public class NoCycleSP {

	/**
	 * 原点
	 */
	private int s;

	/**
	 * dist[i]表示s->i的距离
	 */
	private double[] dist;

	/**
	 * 最短路径上的前驱顶点
	 */
	private int[] prev;

	public NoCycleSP(WeightDigraph g, int s) {
		int v = g.v();
		this.s = s;

		dist = new double[v];

		prev = new int[v];

		for (int i = 0; i < v; i++) {
			prev[i] = -1;
			dist[i] = Double.POSITIVE_INFINITY;
		}

		dist[s] = 0.0;

		// 将权重有向图转成无权有向图图,然后进行拓扑排序
		Topological top = new Topological(g.toDigraph());

		for (int i : top.order()) {
			relax(i, g);
		}
	}

	/**
	 *
	 * @Title: relax
	 * @Description: 松弛某个顶点周围的边
	 * @param @param i
	 * @param @param g 设定文件
	 * @return void 返回类型
	 * @throws
	 */
	private void relax(int i, WeightDigraph g) {
		for (Edge edge : g.adj(i)) {
			int j = edge.otherSide(i);

			if (dist[j] > dist[i] + edge.weight()) {
				dist[j] = dist[i] + edge.weight();
				prev[j] = i;
			}
		}
	}

	/**
	 *
	 * @Title: distTo
	 * @Description: s->v的最短距离
	 * @param @param v
	 * @param @return 设定文件
	 * @return double 返回类型
	 * @throws
	 */
	public double distTo(int v) {
		return dist[v];
	}

	/**
	 *
	 * @Title: pathTo
	 * @Description: 最短路径
	 * @param @param v
	 * @param @return 设定文件
	 * @return Iterable<Integer> 返回类型
	 * @throws
	 */
	public Iterable<Integer> pathTo(int v) {
		if (distTo(v) == Double.POSITIVE_INFINITY)
			return null;

		Stack<Integer> path = new Stack<Integer>();

		for (int i = v; i != -1; i = prev[i]) {
			path.push(i);
		}
		return path;
	}

	public static void main(String[] args) {
		WeightDigraph g = new WeightDigraph(new In(
				"F:\\算法\\attach\\tinyEWDAG.txt"));

		//由于无法从其他节点到达5节点(拓扑排序第一个节点),所以这里我们采用5节点作为第一个节点,来观察所有的可达路径
		NoCycleSP d = new NoCycleSP(g, 5);

		for (int i = 0; i < g.v(); i++) {
			Iterable<Integer> path = d.pathTo(i);
			if (path == null) {
				System.out.println("从原点" + d.s + "到" + i + "没有可达路径");
			} else {
				System.out.println("从原点" + d.s + "到" + i + "的最短距离为:"
						+ d.distTo(i));
				System.out.print("路径为:");
				for (int j : d.pathTo(i)) {
					System.out.print(j + "->");
				}
				System.out.println();
			}
		}
	}
}

文本数据:

8
13
5 4 0.35
4 7 0.37
5 7 0.28
5 1 0.32
4 0 0.38
0 2 0.26
3 7 0.39
1 3 0.29
7 2 0.34
6 2 0.40
3 6 0.52
6 0 0.58
6 4 0.93

这个无环图的输出结果为:

从原点5到0的最短距离为:0.73
路径为:5->4->0->
从原点5到1的最短距离为:0.32
路径为:5->1->
从原点5到2的最短距离为:0.6200000000000001
路径为:5->7->2->
从原点5到3的最短距离为:0.61
路径为:5->1->3->
从原点5到4的最短距离为:0.35
路径为:5->4->
从原点5到5的最短距离为:0.0
路径为:5->
从原点5到6的最短距离为:1.13
路径为:5->1->3->6->
从原点5到7的最短距离为:0.28
路径为:5->7->
时间: 2024-10-29 10:46:47

算法导论——有向无环加权图的最短路径的相关文章

有向无环图的最短路径

我们已经知道了如何通过Dijkstra算法在非负权图中找到最短路径.即使图中有负权边,我们也知道通过Bellman-Ford算法找到一个从 给定的源点到其它所有节点的最短路径.现在我们将看到一个在线性时间内运行得更快的算法,它可以在有向无环图中找到从一个给定的源点到其它所有可达顶点的 最短路径,又名有向无环图(DAG). 由于有向无环图无环所以我们不必担心负环的问题.正如我们已经知道在负环里讨论最短路径是毫无意义的一样,因为我们可以在这些环里不断“循环”,但实际上我们得到的路径将变得越来越短(构

【数据结构】拓扑排序、最短路径算法、Dijkstra算法、无环图等等

图的定义 图(graph)G = (V,E)由顶点(vertex)的集V和边(Edge)的集E组成.有时也把边称作弧(arc),如果点对(v,w)是有序的,那么图就叫做有向的图(有向图).顶点v和w邻接(adjacent)当且仅当(v,w)属于E. 如果无向图中从每一个顶点到其他每个顶点都存在一条路径,则称该无向图是连通的(connected).具有这样性质的有向图称为是强连通的(strongly connected).如果有向图不是强连通的,但它的基础图(underlying graph)(也

javascript实现有向无环图中任意两点最短路径的dijistra算法

有向无环图 一个无环的有向图称做有向无环图(directed acycline praph).简称DAG 图.DAG 图是一类较有向树更一般的特殊有向图, dijistra算法 摘自 http://www.cnblogs.com/biyeymyhjob/archive/2012/07/31/2615833.html 1.定义概览 Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径.主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止.Dijk

数据结构与算法——有向无环图的拓扑排序C++实现

拓扑排序简介: 拓扑排序是对有向无环图的顶点的一种排序,它使得如果存在一条从Vi到Vj的路径,那么在排序中Vi在Vj的前面. 如果图中含有回路,那么拓扑排序是不可能的.此外,拓扑排序不必是唯一的,任何合理的排序都可以. 对于上面的无环图:v1,v2,v5,v4,v3,v7,v6和v1,v2,v5,v4,v7,v3,v6都是合理的拓扑排序. 一个简单的求拓扑排序的思路: 1.先找出任意一个没有入边的顶点 2.然后显出该点,并将它和它邻接的所有的边全部删除. 3.然后,对图中其它部分做同样的处理.

[从今天开始修炼数据结构]无环图的应用 —— 拓扑排序和关键路径算法

上一篇文章我们学习了最短路径的两个算法.它们是有环图的应用.下面我们来谈谈无环图的应用. 一.拓扑排序 博主大学学的是土木工程,在老本行,施工时很关键的节约人力时间成本的一项就是流水施工,钢筋没绑完,浇筑水泥的那帮兄弟就得在那等着,所以安排好流水施工,让工作周期能很好地衔接就很关键.这样的工程活动,抽象成图的话是无环的有向图. 在表示工程的有向图中,用顶点表示活动,弧表示活动之间的优先关系,这样的有向图为顶点表示活动的网,成为AOV网(Active On Vertex Network) ※ 若在

UVA10305 Ordering Tasks(有向无环图排序--toposort) Kahn算法

题目描述:https://vjudge.net/problem/UVA-10305 题目分析: 恨水的题目,只要学了toposort就会做的,大概意思是给你n个变量,m个不等关系表示a<b,问n个数可能的关系;不如举个例子例如n=3表示3个变量我们假如他们是a,b,c现在有两个关系a<b,a<c 那么输出有两种a<b<c或者a<c<b(题目要求输出任意一种); 题目大概就这个意思,那么我们怎么做呢,我们想一想如果把变量看成点,关系看成有向边,那么就得到一个图,这个

[算法天地]关于单链表的操作有环无环判断

#include <stdio.h> #include <stdlib.h> // 有环链表的各种函数测试 typedef struct Node { int data; struct Node *next; }Node; typedef struct Node* LinkList; /*链表初始化*/ int InitList(LinkList *L) { *L = (LinkList)malloc(sizeof(Node)); if(!(*L)) return -1; (*L)

基本数据结构(算法导论)与python

原文链接 Stack, Queue Stack是后进先出, LIFO, 队列为先进先出, FIFO在Python中两者, 都可以简单的用list实现,进, 用append()出, Stack用pop(), Queue用pop(0), pop的时候注意判断len(l) 对于优先队列, 要用到前面讲到的堆 链表和多重数组 这些数据结构在python中就没有存在的价值, 用list都能轻松实现 散列表 为了满足实时查询的需求而产生的数据结构, 查询复杂度的期望是O(1), 最差为O(n)问题描述, 对

并行计算有向无环图和fork/join 框架

从多任务OS开始,线程主要用来表示IO异步:而今随着4G和多核等的到来,计算密集型又热门起来了. 硬件价格和性能从低到高: PC/Laptop multi core, memory shared PC clusters SuperComputers 假设一个理想并行计算机:每个处理器计算能力相同,忽略调度, static thread 是对一个虚拟处理器的软件层面的抽象; static强调的是线程一直存在,不包含线程的创建和销毁. dynamic multithreded concurrency