1. 程式人生 > 其它 >SPFA 最短路演算法

SPFA 最短路演算法

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++;
	}
}