package com.xjj.lanqiao;
import java.util.Scanner;
/*----Bellman - ford算法------
* 是求含“负权”图的“单源最短路径”的一种算法,效率较低,代码难度较小。
* 其原理为连续进行松弛,在每次松弛时把每条边都更新一下,
*
* 1. 第一个节点到其他节点的最小距离
* 2. 图的任意一条最短路径既不能包含负权回路,也不会包含正权回路
* 3. 三个数组存 start,end,Wi
* 4. 还可检测一个图中是否含有负权回路
*
* 5.时间复杂度 = O(mn)
* */
public class Lq3_5 {
static int flag = 0;
public static int[] method(int[] start,int[] end,int[] w,int n){
//不要用Integer.Max, 下面值会变,如2147483647+2 = -2147483647
int Inf = 99999999;
int m = start.length;
int[] dis = new int[n+1];
for(int i = 1; i <= n; i++)
dis[i] = Inf;
dis[1] = 0;
//核心4行代码
for(int j = 1; j <= n-1; j++) //指1号顶点最多经过n-1条边到达其余各点的最短距离
for(int i = 1; i < m; i++){ //枚举每一条边
//看看能否通过 start[i]->end[i] (w[i]为其权值),使1号顶点到end[i]点的距离变短
if (dis[end[i]] > dis[start[i]] + w[i]) {
dis[end[i]] = dis[start[i]] + w[i];
}
}
//判断负权回路
for(int i = 1; i < m; i++)
//如果进行n-1次松弛后最短路仍然变化,则存在负权回路
if (dis[end[i]] > dis[start[i]] + w[i]) {
flag = 1;
}
return dis;
}
public static void main(String[] args) {
System.out.println("输入点及边:");
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int m = scanner.nextInt();
int[] s = new int[m+1];
int[] e = new int[m+1];
int[] w = new int[m+1];
//开始,尾,权
for(int i = 1; i <= m; i++){
int a = scanner.nextInt();
int b = scanner.nextInt();
int c = scanner.nextInt();
s[i] = a; //起点
e[i] = b; //终点
w[i] = c; //权值
}
int[] result = method(s, e, w,n);
if (flag == 0) {
System.out.println("一号顶点到其他顶点的最短距离为: ");
for(int i = 1; i <= n; i++)
System.out.print(result[i] + " ");
}
else {
System.out.println("此图含有负权回路.");
}
}
}
Bellman - ford算法--单源最短路径
最新推荐文章于 2024-05-19 16:50:57 发布