定义:在一幅加权有向图中,从顶点s到顶点t的最短路径是所有从s到t的路径中权重最小者。
(单源最短路径、单终点最短路径、单对顶点最短路径、每对顶点最短路径)
引理:最短路径的子路径是最短路径。
当且仅当加权有向图中至少存在一条从s到v的有向图路径且所有从s到v的有向路径上的任意顶点都不存在于任何负权重环中时,s到v的最短路径才是存在的。
松弛(relaxation)操作
Bellman-Ford算法
利用松弛技术,对每个属于V的顶点v,逐步减小从源s到v的最短路径的权的估计值d[v],直到其到达实际最短路径的权w(s, v)。当图中不包含从源点可达的负权回路时,算法返回TRUE;否则,返回FALSE。
package mysp;
import edu.princeton.cs.algs4.In;
import edu.princeton.cs.algs4.StdDraw;
import edu.princeton.cs.algs4.StdOut;
import myutil.*;
public class MyBellmanFordSP {
private double[] distTo;
private MyDiEdge[] edgeTo;
private boolean[] onQueue;
private MyQueue<Integer> queue;
private int cost;
private Iterable<MyDiEdge> cycle;
public MyBellmanFordSP(MyEWDigraph G, int s) {
distTo = new double[G.V()];
edgeTo = new MyDiEdge[G.V()];
onQueue = new boolean[G.V()];
queue = new MyQueue<Integer>();
for (int v = 0; v < G.V(); v++) {
distTo[v] = Double.POSITIVE_INFINITY;
}
distTo[s] = 0.0;
queue.enqueue(s);
onQueue[s] = true;
while (!queue.isEmpty() && !this.hasNegativeCycle()) {
int v = queue.dequeue();
onQueue[v] = false;
relax(G, v);
}
}
private void relax(MyEWDigraph G, int v) {
for (MyDiEdge e : G.adj(v)) {
int w = e.to();
if (distTo[w] > distTo[v] + e.weight()) {
distTo[w] = distTo[v] + e.weight();
edgeTo[w] = e;
if (!onQueue[w]) {
queue.enqueue(w);
onQueue[w] = true;
}
}
if (cost++ % G.V() == 0) {
findNegativeCycle();
}
}
}
public double distTo(int v) {
return distTo[v];
}
public boolean hasPathTo(int v) {
return distTo[v] < Double.POSITIVE_INFINITY;
}
public Iterable<MyDiEdge> pathTo(int v) {
if (!hasPathTo(v)) {
return null;
}
MyStack<MyDiEdge> path = new MyStack<MyDiEdge>();
for (MyDiEdge e = edgeTo[v]; e != null; e = edgeTo[e.from()]) {
path.push(e);
}
return path;
}
private void findNegativeCycle() {
int V = edgeTo.length;
MyEWDigraph spt = new MyEWDigraph(V);
for (int v = 0; v < V; v++) {
if (edgeTo[v] != null) {
spt.addEdge(edgeTo[v]);
}
}
MyEWDiCycle cf = new MyEWDiCycle(spt);
cycle = cf.cycle();
}
public boolean hasNegativeCycle() {
return cycle != null