1. Problem Definition:
Given an edge-weighted digraph, find the shortest path from s to t.
2. Different Vertices:
-- Source-sink: from one vertex to another.
-- Single source: from one vertex to every other.
-- All pairs: between all pairs of vertices.
3. Weighted directed edge: implementation in Java
public class DirectedEdge { private final int v, w; private final double weight; public DirectedEdge(int v, int w, double weight) { this.v = v; this.w = w; this.weight = weight; } public int from() { return v; } public int to() { return w; } public int weight() { return weight; } String toString() { return v + "->" + w; } }
4. Edge-weighted digraph: adjacency-lists implementation in Java
public class EdgeWeightedDigraph { private final int V; private final Bag<Edge>[] adj; public EdgeWeightedDigraph(int V) { this.V = V; adj = (Bag<DirectedEdge>[]) new Bag[V]; for (int v = 0; v < V; v++) adj[v] = new Bag<DirectedEdge>(); } public void addEdge(DirectedEdge e) { int v = e.from(); adj[v].add(e); } public Iterable<DirectedEdge> adj(int v) { return adj[v]; } }
5. Single-source shortest paths API
public class SP { SP(EdgeWeightedDigraph G, int s) {} //shortest paths from s in graph G double distTo(int v) {} //length of shortest path from s to v Iterable <DirectedEdge> {} //pathTo(int v) shortest path from s to v boolean hasPathTo(int v) {} //is there a path from s to v? }
6. Data structures for single-source shortest paths: Can represent the SPT with two vertex-indexed arrays:
-- distTo[v] is length of shortest path from s to v.
-- edgeTo[v] is last edge on shortest path from s to v.
7. Relax edge e = v→w.
-- distTo[v] is length of shortest known path from s to v.
-- distTo[w] is length of shortest known path from s to w.
-- edgeTo[w] is last edge on shortest known path from s to w.
-- If e = v→w gives shorter path to w through v, update both distTo[w] and edgeTo[w].
8. Shortest-paths optimality conditions:
distTo[] are the shortest path distances from s iff -->
-- For each vertex v, distTo[v] is the length of some path from s to v.
-- For each edge e = v→w, distTo[w] ≤ distTo[v] + e.weight().
Pf. ==> [necessary]
-- Suppose that distTo[w] > distTo[v] + e.weight() for some edge e = v→w.
-- Then, e gives a path from s to w (through v) of length less than distTo[w].
Pf. <== [sufficient]
-- Suppose that s = v0 → v1 → v2 → … → vk = w is a shortest path from s to w.
-- Then, distTo[w] = distTo[vk] ≤ distTo[vk-1] + ek.weight() ≤ distTo[vk-2] + ek-1.weight() + ek.weight()
≤ e1.weight() + e2.weight() + ... + ek.weight() (weight of shortest path)
-- Thus, distTo[w] is the weight of shortest path to w.
9. Generic shortest-paths algorithm:
-- Initialize distTo[s] = 0 and distTo[v] = ∞ for all other vertices.
-- Repeat until optimality conditions are satisfied:
-- Relax any edge.
Pf. of correctness
-- Throughout algorithm, distTo[v] is the length of a simple path from s to v (and edgeTo[v] is last edge on path).
-- Each successful relaxation decreases distTo[v] for some v.
-- The entry distTo[v] can decrease at most a finite number of times.
How to choose which edge to relax?
-- Dijkstra's algorithm (nonnegative weights).
-- Topological sort algorithm (no directed cycles).
-- Bellman-Ford algorithm (no negative cycles).
10. Dijkstra's algorithm:
-- Consider vertices in increasing order of distance from s
(non-tree vertex with the lowest distTo[] value).
-- Add vertex to tree and relax all edges pointing from that vertex.
Java implementation:
public class DijkstraSP { private DirectedEdge[] edgeTo; private double[] distTo; private IndexMinPQ<Double> pq; public DijkstraSP(EdgeWeightedDigraph G, int s) { edgeTo = new DirectedEdge[G.V()]; distTo = new double[G.V()]; pq = new IndexMinPQ<Double>(G.V()); for (int v = 0; v < G.V(); v++) distTo[v] = Double.POSITIVE_INFINITY; distTo[s] = 0.0; pq.insert(s, 0.0); while (!pq.isEmpty()) { int v = pq.delMin(); for (DirectedEdge e : G.adj(v)) relax(e); } } private void relax(DirectedEdge e) { int v = e.from(), w = e.to(); if (distTo[w] > distTo[v] + e.weight()) { distTo[w] = distTo[v] + e.weight(); edgeTo[w] = e; if (pq.contains(w)) pq.decreaseKey(w, distTo[w]); else pq.insert (w, distTo[w]); } } }
Running Time:
11. Main distinction between Dijkstra's and Prims algorithm : Rule used to choose next vertex for the tree:
-- Prim’s: Closest vertex to the tree (via an undirected edge).
-- Dijkstra’s: Closest vertex to the source (via a directed path).
12. Shortest paths in edge-weighted DAGs:
-- Consider vertices in topological order.
-- Relax all edges pointing from that vertex.
Java Implementation:
public class AcyclicSP { private DirectedEdge[] edgeTo; private double[] distTo; public AcyclicSP(EdgeWeightedDigraph G, int s) { edgeTo = new DirectedEdge[G.V()]; distTo = new double[G.V()]; for (int v = 0; v < G.V(); v++) distTo[v] = Double.POSITIVE_INFINITY; distTo[s] = 0.0; Topological topological = new Topological(G); for (int v : topological.order()) for (DirectedEdge e : G.adj(v)) relax(e); } }
13. Longest paths in edge-weighted DAGs:
-- Negate all weights.
-- Find shortest paths.
-- Negate weights in result.
Application: Parallel job scheduling. Given a set of jobs with durations and precedence constraints, schedule the jobs (by finding a start time for each) so as to achieve the minimum completion time, while respecting the constraints.
Solution: Critical path method -- create edge-weighted DAG:
-- Source and sink vertices.
-- Two vertices (begin and end) for each job.
-- Three edges for each job.
– begin to end (weighted by duration)
– source to begin (0 weight)
– end to sink (0 weight)
-- One edge for each precedence constraint (0 weight).
-- Use longest path from the source to schedule each job.
14. Bellman-Ford algorithm
-- Initialize distTo[s] = 0 and distTo[v] = ∞ for all other vertices.
-- Repeat V times:
- Relax each edge.
for (int i = 0; i < G.V(); i++) for (int v = 0; v < G.V(); v++) for (DirectedEdge e : G.adj(v)) relax(e);
Optimization: If distTo[v] does not change during pass i, no need to relax any edge pointing from v in pass i+1.
FIFO implementation: Maintain queue of vertices whose distTo[] changed. (Be careful to keep at most one copy of each vertex on queue.
Running Time :
Finding a negative cycle : If any vertex v is updated in phase V, there exists a negative cycle (and can trace back edgeTo[v] entries to find it).
15. Negative cycle application: arbitrage detection:
Given table of exchange rates, is there an arbitrage opportunity?
Currency exchange graph:
-- Vertex = currency.
-- Edge = transaction, with weight equal to exchange rate.
-- Find a directed cycle whose product of edge weights is > 1.
Model as a negative cycle detection problem by taking logs.
-- Let weight of edge v→w be - ln (exchange rate from currency v to w).
-- Multiplication turns to addition; > 1 turns to < 0.
-- Find a directed cycle whose sum of edge weights is < 0 (negative cycle).
16. Shortest paths summary
Dijkstra’s algorithm:
-- Nearly linear-time when weights are nonnegative.
-- Generalization encompasses DFS, BFS, and Prim.
Acyclic edge-weighted digraphs:
-- Arise in applications.
-- Faster than Dijkstra’s algorithm.
-- Negative weights are no problem.
Negative weights and negative cycles:
-- Arise in applications.
-- If no negative cycles, can find shortest paths via Bellman-Ford.
-- If negative cycles, can find one via Bellman-Ford.
相关推荐
本文将深入探讨一种基于K最短路径(K-Shortest Paths, KSP)优化算法在多目标跟踪中的应用,并以C++编程语言为实现基础。 多目标跟踪的目标是通过分析视频帧间的相似性来维持目标的身份一致性,即使在遮挡、重叠或...
Finding Top-k Shortest Paths with Diversity 在计算机科学和信息技术领域中,寻找 Top-k 最短简单路径问题是一个经典的问题。该问题的应用非常广泛,例如在路线规划、交通导航、物流等领域都有重要的实践价值。本...
### Undirected Single-Source Shortest Paths with Positive Integer Weights in Linear Time #### 一、引言 本研究由Mikkel Thorup于1999年发表在《ACM通讯》上,主要解决了无向图中单源最短路径问题(Single-...
这里仅给出了C++的实现方法,详细的数学证明请参见相关论文。特别要指出的是葡萄牙教授Martins对此算法有深入研究,发表了为数众多的相关论文,我这里采用的也是基于他早期提出的deletion algorithm。...
Single-source shortest paths. The following is the adjacency matrix, vertex A is the source. A B C D E A -1 3 B 3 2 2 C D 1 5 E -3 All-pairs shortest paths. The adjacency matrix is as ...
k-Shortest Paths(k-最短路径)则是在这个基础上进一步扩展,不仅求解一条最短路径,而是找出前k条最短路径。 1. Dijkstra算法:Dijkstra算法是最基本的单源最短路径算法,由荷兰计算机科学家艾兹格·迪科斯彻提出...
queue.isEmpty() && shortestPaths.size() ) { Path currentPath = queue.poll(); if (currentPath.current == destination) { shortestPaths.add(currentPath); continue; } List<Edge> edges = graph.get...
在这个"基于java的最短路径算法实现 k-shortest-paths.zip"压缩包中,很显然包含了一个用Java实现的求解最短路径问题的程序,尤其是K-Shortest Paths(K条最短路径)算法。 K-Shortest Paths算法是一种扩展了...
基于java的开发源码-最短路径算法实现 k-shortest-paths.zip 基于java的开发源码-最短路径算法实现 k-shortest-paths.zip 基于java的开发源码-最短路径算法实现 k-shortest-paths.zip 基于java的开发源码-最短路径...
标题"Algortihms-ShortestPaths:计算最短路径的数量"表明我们关注的是计算从一个源节点到图中所有其他节点的最短路径数量。这不仅包括找到单个最短路径,还涉及到统计这些路径的总数。这个任务可以用于理解网络的...
"基于Java的最短路径算法实现 k-shortest-paths.zip" 是一个压缩包,其中包含了用Java编程语言实现的一种算法,该算法旨在找到图中两个节点之间的多条最短路径,即k最短路径(K-Shortest Paths, KSP)。在这个讨论中...
if shortestPaths(i, k) + shortestPaths(k, j) < shortestPaths(i, j) shortestPaths(i, j) = shortestPaths(i, k) + shortestPaths(k, j); end end end end end ``` 其中`graph`是一个邻接矩阵,表示图的边...
if shortestPaths(i, j) > shortestPaths(i, k) + shortestPaths(k, j) shortestPaths(i, j) = shortestPaths(i, k) + shortestPaths(k, j); end end end end end ``` 在这个函数中,`graph`参数是邻接矩阵,...
if shortestPaths(i, j) > shortestPaths(i, k) + shortestPaths(k, j) shortestPaths(i, j) = shortestPaths(i, k) + shortestPaths(k, j); end end end end end ``` 这个函数接收一个邻接矩阵`graph`作为...
1. **初始化**:创建一个`n x n`的矩阵`shortestPaths`,其中`shortestPaths[i][j]`初始化为`arcs[i][j]`,表示从顶点`i`到`j`的最短路径。对于所有直接相连的顶点,`shortestPaths[i][j]`等于边的权重;对于不直接...
if shortestPaths[i][j] > shortestPaths[i][k] + shortestPaths[k][j] shortestPaths[i][j] = shortestPaths[i][k] + shortestPaths[k][j]; end end end end end ``` 在实际应用中,你可以将此函数与MATLAB...
if shortestPaths(i, j) > shortestPaths(i, k) + shortestPaths(k, j) shortestPaths(i, j) = shortestPaths(i, k) + shortestPaths(k, j); end end end end end ``` 在实际的数学建模问题中,我们可能需要...
if shortestPaths(i, j) > shortestPaths(i, k) + shortestPaths(k, j) shortestPaths(i, j) = shortestPaths(i, k) + shortestPaths(k, j); end end end end end ``` 在这个代码中,`graph`是输入的邻接矩阵...