图(五):最短路径

定义:在一幅加权有向图中,从顶点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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值