SPFA 算法是 Bellman-Ford 算法的队列优化算法,通常用于求解负权边的单源最短路径,以及判断负环。在最坏的情况下,SPFA 算法的时间复杂度和 Bellman-Ford 算法相同,为O(nm);但在系数图上运行效率较高,为 O(km),其中 k 是一个较小的常数。
1 创建一个队列,首先源点 u 入队,标记 u 在队列中,u 的入队次数加1。
2 松弛操作。取出队头节点 x,标记 x 不在队列中。扫描所有 x 的所有出边 i(x,v,w),如果 dis[v]>dis[x]+e[i].w,令 dis[v]=dis[x]+e[i].w。如果节点 v 不在队列中,判断 v 的入队此时加1后大于或等于 n,则说明有负环,退出;否则 v 入队,标记 v 在队列中。
3 重复松弛操作,直到队列为空。
package graph.spfa;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
public class Spfa {
static final int maxn = 505;
static final int maxe = 100001;
static int n;
static int m;
static int cnt;
static node e[] = new node[maxn];
static int head[] = new int[maxn];
static int dis[] = new int[maxn];
static int sum[] = new int[maxn];
static boolean vis[] = new boolean[maxn];
static {
for (int i = 0; i < e.length; i++) {
e[i] = new node();
}
for (int i = 0; i < head.length; i++) {
head[i] = -1;
}
}
static void add(int u, int v, int w) {
e[cnt].to = v;
e[cnt].next = head[u];
e[cnt].w = w;
head[u] = cnt++;
}
static boolean spfa(int u) {
Queue<Integer> q = new LinkedList<>();
for (int i = 0; i < vis.length; i++) {
vis[i] = false;
}
// 统计入队的次数
for (int i = 0; i < sum.length; i++) {
sum[i] = 0;
}
for (int i = 0; i < dis.length; i++) {
dis[i] = 0x3f;
}
vis[u] = true;
dis[u] = 0;
sum[u]++;
q.add(u);
while (!q.isEmpty()) {
int x = q.peek();
q.poll();
vis[x] = false;
for (int i = head[x]; i >= 0; i = e[i].next) {
int v = e[i].to;
if (dis[v] > dis[x] + e[i].w) {
dis[v] = dis[x] + e[i].w;
if (!vis[v]) {
if (++sum[v] >= n)
return true;
vis[v] = true;
q.add(v);
}
}
}
}
return false;
}
static void print() { // 输出源点到其它节点的最短距离
System.out.println("最短距离:");
for (int i = 1; i <= n; i++)
System.out.print(dis[i] + " ");
System.out.println();
}
public static void main(String[] args) {
cnt = 0;
Scanner scanner = new Scanner(System.in);
n = scanner.nextInt();
m = scanner.nextInt();
int u, v, w;
for (int i = 1; i <= m; i++) {
u = scanner.nextInt();
v = scanner.nextInt();
w = scanner.nextInt();
add(u, v, w);
}
if (spfa(1))
System.out.println("有负环!");
else
print();
}
}
class node {
int to;
int w;
int next;
}
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://blog.csdn.net/chengqiuming/article/details/125694516
内容来源于网络,如有侵权,请联系作者删除!