经典算法之图的最短路径(二):Bellman_Ford算法

Bellman_Ford算法也是一个求图的最短路径的非常经典的算法,它适用于求单源最短路径,相比于同样用于单源最短路径的Dijkstra算法,它的适用范围更广,它可以用于有向图和无向图,并且权值可以为负,如果存在负权回路,可输出提示。

算法的流程就是:每次遍历图中所有边进行松弛(所谓的松弛是这样的——比如说存在一条边e(u,v),权值为w(u,v),如果d(v)>d(u)+w(u,v),则让d(v)=d(u)+w(u,v)),共遍历松弛V-1次(V是点的个数),此时如果不存在负权回路的话,d[i]就是源点到点i 的最短路径,因此再进行一次遍历,查看是否存在d(v)>d(u)+w(u,v),若存在,说明有负权值回路。下面上代码:(同样是偷懒没有正向打印路径)

package classic;

import java.util.Scanner;

public class Bellman_Ford {

	static int start = 0, V = 0, E = 0;
	static int[][] G = null;
	static int[] d = null, pre = null;
	
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		System.out.println("输入点和边的数目:");
		V = sc.nextInt();//总共有多少个点
		E = sc.nextInt();//总共有多少个边
		
		G = new int[V][V];//用来存放图的信息
		d = new int[V];//用来存放从起点到每个点的最短路径长度
		pre = new int[V];//用来存放每个点在其最短路径上的前一个结点
		
		for(int x=0; x<V; x++){
			for(int y=0; y<V; y++){
				G[x][y] = Integer.MIN_VALUE;
			}
		}
		System.out.println("依次输入每条边的起点、终点和权值:(点的编号从0开始)");
		for(int i=0; i<E; i++){//初始化图
			int u = sc.nextInt();
			int v = sc.nextInt();
			int value = sc.nextInt();
			G[u][v] = value;
			G[v][u] = value;//注意:假如为有向图,则不加这一行!!
		}
		for(int i=0; i<V; i++){//初始化d
			if(i==start)
				d[i] = 0;
			else
				d[i] = Integer.MAX_VALUE/2;
		}
		
		if(!bellman_ford())
			System.out.println("图中存在负权值环");
		else{//打印
			for(int i=0; i<V; i++){
				System.out.println("起点"+start+"到点"+i+"的最短路径长度为:"+d[i]);
				System.out.println("最短路径为:");
				int curv = i;
				System.out.print(i+"<-");
				while(true){
					curv = pre[curv];
					if(curv == start)
						break;
					System.out.print(curv+"<-");
				}
				System.out.println(start);
			}
		}
		sc.close();
	}
	
	static boolean bellman_ford(){
		for(int i=1; i<V; i++){//对每条边都松弛V-1次
			for(int x=0; x<V; x++){
				for(int y=0; y<V; y++){
					if(G[x][y]>Integer.MIN_VALUE){//说明有边
						if(d[y]>d[x]+G[x][y]){
							d[y] = d[x]+G[x][y];
							pre[y] = x;
						}
					}
				}
			}
		}
		for(int x=0; x<V; x++){
			for(int y=0; y<V; y++){
				if(G[x][y]>Integer.MIN_VALUE){//说明有边
					if(d[y]>d[x]+G[x][y]){
						return false;
					}
				}
			}
		}
		return true;
	}

}

    原文作者:Bellman - ford算法
    原文地址: https://blog.csdn.net/silent_strings/article/details/48178429
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞