SPFA算法

/* 改进的BellMan-Ford算法 SPFA
 * 含有负权图的单源最短路径  最短路径如果存在,一定不含环
 * 存在负环时最短路径不存在 当一个节点入队超过n次时说明图中存在负环
 * 使用邻接表和队列实现  每次更新节点时只更新与之相关联的节点
 * d[i]表示节点0到节点i的最短路径
 * */
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Scanner;

public class BellmanFord {
	static final int MAX = 1 << 30;

	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);
		int n = scanner.nextInt();
		int m = scanner.nextInt();
		int[] u = new int[m];// 边的起点
		int[] v = new int[m];// 边的终点
		int[] w = new int[m];// 边权
		int[] first = new int[m];// frist[u]以u为起点的第一条边
		Arrays.fill(first, -1);// 初始化表头
		int[] next = new int[m];// next[i]编号为i的边的下一条边
		int[] d = new int[n];
		int[] count = new int[n];// 节点进队列的次数
		Arrays.fill(d, MAX);
		d[0] = 0;
		int[] inq = new int[n];// 节点是否在队列中
		int[] fa = new int[n];// 记录路径
		boolean circle = false;
		LinkedList<Integer> queue = new LinkedList<Integer>();
		for (int e = 0; e < m; e++) {
			u[e] = scanner.nextInt();
			v[e] = scanner.nextInt();
			w[e] = scanner.nextInt();
			next[e] = first[u[e]];
			first[u[e]] = e;
		}
		queue.offer(0);
		count[0]++;
		while (queue.size() > 0) {
			int x = queue.poll();
			inq[x] = 0;// 清除在队列中标识
			for (int e = first[x]; e != -1; e = next[e]) {
				if (d[v[e]] > d[x] + w[e]) {
					d[v[e]] = d[x] + w[e];
					fa[v[e]] = x;
					if (inq[v[e]] == 0) {// 不在队列中才添加
						if (count[v[e]] == n) {
							System.out.println("存在负环");
							circle = true;
							return;
						}
						inq[v[e]] = 1;
						count[v[e]]++;
						queue.offer(v[e]);
					}
				}
			}
		}
		if (!circle) {
			for (int i = 0; i < n; i++) {
				if (i == 0) {
					System.out.println(0);
					continue;
				} else {
					System.out.printf("%d<-", i);
					int t = fa[i];
					while (t > 0) {
						System.out.printf("%d<-", t);
						t = fa[t];
					}
				}
				System.out.println(0 + "  the minmum length is " + d[i]);
			}
		}
	}
}
输入:
4
5
0 1 -1
1 2 -2
2 0 4
2 3 -3
0 3 1
输出
0
1<-0  the minmum length is -1
2<-1<-0  the minmum length is -3
3<-2<-1<-0  the minmum length is -6


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值