SPFA算法

算法的思路: 
我们用数组dis记录每个结点的最短路径估计值,用邻接表或邻接矩阵来存储图G。我们采取的方法是动态逼近法:设立一个先进先出的队列用来保存待优化的结点,优化时每次取出队首结点u,并且用u点当前的最短路径估计值对离开u点所指向的结点v进行松弛操作,如果v点的最短路径估计值有所调整,且v点不在当前的队列中,就将v点放入队尾。这样不断从队列中取出结点来进行松弛操作,直至队列空为止

我们要知道带有负环的图是没有最短路径的,所以我们在执行算法的时候,要判断图是否带有负环,方法有两种:

  1. 开始算法前,调用拓扑排序进行判断(一般不采用,浪费时间)

 

  1. 如果某个点进入队列的次数超过N次则存在负环(N为图的顶点数)

判断有无负环:如果某个点进入队列的次数超过N次则存在负环(SPFA无法处理带负环的图)

 

import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;


public class SPFA算法 {
static int INF = Integer.MAX_VALUE;
public static void main(String[] args){
Scanner scanner = new Scanner(System.in);
int nodes = scanner.nextInt();
int edges = scanner.nextInt();
int weight[][] = new int[nodes][nodes];
//初始化矩阵,都为无穷大,除了自己与自己
for(int i = 0; i < nodes; i++){
for(int j = 0; j < nodes; j++){
if(i == j){
weight[i][j] = 0;
}else{
weight[i][j] = INF;
}
}
}
for(int i = 0; i < edges; i++){
int start = scanner.nextInt();
int end = scanner.nextInt();
int value = scanner.nextInt();
weight[start - 1][end - 1] = value;
}
int path[] = new int[nodes];
int dist[] = new int[nodes];
Spfa(nodes, dist, path, weight);
scanner.close();
}
private static void Spfa(int n, int[] dist, int[] path, int[][] weight) {
// TODO Auto-generated method stub
//初始化
for(int i = 0; i < n; i++){
dist[i] = INF;
}
Queue<Integer> queue = new LinkedList<Integer>();
int visited[] = new int[n];
queue.offer(0);                //将第一个顶点添加进去,并且标记为已被访问,1表示被访问
visited[0] = 1;
dist[0] = 0;
while(!queue.isEmpty()){
int out = queue.poll();
//对于第一个出队的顶点找他的相邻点并且进行比较
for(int i = 0; i < n; i++){
if(weight[out][i] != INF && dist[i] > dist[out] + weight[out][i]){
dist[i] = dist[out] + weight[out][i];              //更新dist的数据
if(visited[i] == 0){
queue.offer(i);
visited[i] = 1;
path[out] = i;
}
}
}
visited[out] = 0;               //找出所有相邻的点更新后重新标志,因为out出队列了,要再次标记为0
}
for(int i = 0; i < n; i++){
if(dist[i] == INF){
System.out.println("点" + i +"距离为无穷大");
continue;
}
System.out.println("点0到" + i +"距离为" + dist[i]);
}
}

}

运行结果:

6 8
1 3 10
1 5 30
1 6 100
2 3 5
3 4 50
4 6 10
5 4 20
5 6 60
点0到0距离为0
点1距离为无穷大
点0到2距离为10
点0到3距离为50
点0到4距离为30
点0到5距离为60

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值