SPFA 最短路演算法
阿新 • • 發佈:2022-04-07
SPFA演算法
1、什麼是spfa演算法?
SPFA 演算法是 Bellman-Ford演算法 的佇列優化演算法的別稱,通常用於求含負權邊的單源最短路徑,以及判負權環。SPFA一般情況複雜度是O(m)O(m) 最壞情況下複雜度和樸素 Bellman-Ford 相同,為O(nm)。
2.演算法步驟:
queue <– 1
while queue 不為空
(1) t <– 隊頭
queue.pop()
(2)用 t 更新所有出邊 t –> b,權值為w
queue <– b (若該點被更新過,則拿該點更新其他點)
時間複雜度 一般:O(m) 最壞:O(nm)
n為點數,m為邊數
3、spfa也能解決權值為正的圖的最短距離問題,且一般情況下比Dijkstra演算法還好
題目:
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.Arrays; import java.util.LinkedList; import java.util.Queue; class Main { static int INF = 0x3f3f3f3f; static int N = 100000 + 5; static int[] head = new int[N]; static int[] next = new int[N]; static int[] vv = new int[N]; static int[] ww = new int[N]; static int idx = 0; static int[] dis = new int[N]; static int n; // 當一個點放入queue就為true,取出就為false,防止隊伍裡面有重複元素,減小執行時間 static boolean[] st = new boolean[N]; public static void main(String[] args) throws IOException { init(); BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); String[] line = reader.readLine().split(" "); n = Integer.parseInt(line[0]); int m = Integer.parseInt(line[1]); for (int i = 1; i <= m; i++) { line = reader.readLine().split(" "); int x = Integer.parseInt(line[0]); int y = Integer.parseInt(line[1]); int z = Integer.parseInt(line[2]); add(x, y, z); } spfa(); } private static void spfa() { // queue儲存的是點 Queue<Integer> queue = new LinkedList<Integer>(); st[1] = true; queue.add(1); Arrays.fill(dis, INF); dis[1] = 0; while (!queue.isEmpty()) { int x = queue.poll(); st[x] = false; for (int i = head[x]; i != -1; i = next[i]) { int j = vv[i]; if (dis[j] > dis[x] + ww[i]) { dis[j] = dis[x] + ww[i]; if (!st[j]) { st[j] = true; queue.add(j); } } } } if (dis[n] < INF / 2) { System.out.println(dis[n]); } else { System.out.println("impossible"); } } private static void init() { // TODO Auto-generated method stub Arrays.fill(head, -1); } static void add(int x, int y, int w) { ww[idx] = w; vv[idx] = y; next[idx] = head[x]; head[x] = idx++; } }