演算法:最短路徑問題

CopperDong發表於2017-09-07

    求圖結構中連線兩個給定頂點的最短路徑長度

    本章將介紹找出加權圖最短路徑的一些演算法

一、迪傑斯特拉最短路徑演算法(Dijkstra):

       Dijkstra演算法是單源最短路徑演算法

1、使用優先佇列的寬度優先搜尋

        用優先佇列替代了佇列,BFS將頂點序號儲存到佇列,而Dijkstra會利用優先佇列儲存頂點序號和已找出的到目標頂點的最短距離。至於優先組佇列,則會按照到頂點的最短距離排列各頂點。通過這種過程,在尚未訪問的頂點中找出到起點的距離最短的頂點會變得更簡單。

const int   MAX_V = 100;
int   V;
vector< pair<int, int> > adj[MAX_V];
vector<int>  dijkstra(int src) {
	vector<int>   dist(V, INF);
	dist[src] = 0;
	priority_queue<pair<int, int> > pq;
	pq.push(make_pair(0, src));
	while (!pq.empty()) {
		int   cost = -pq.top().first;
		int   here = pq.top().second;
		pq.pop();
		// if there are some more shorter path than the current path, then igorne the current path
		if (dist[here] < cost)  continue;
		//
		for (int i=0; i<adj[here].size(); ++i) {
			int there = adj[here][i].first;
			int nextDist = cost + adj[here][i].second;
			//
			if (dist[there] > nextDist) {
				dist[there] = nextDist;
				pq.push(make_pair(-nextDist, there));
			}
		}//
	}
}
二、貝爾曼-福特最短路徑演算法(Bellman-Ford)

      求某個起點到其他頂點的最短距離時,dijkstra演算法最有用。不過,對帶有負權邊的圖結構,dijkstra將無法保障其正確性。為了解決這種問題,Bellman-Ford應運而生。與dijkstra演算法相同,bellman-ford演算法也是單源最短路徑演算法,但它能夠對帶有負權邊的圖結構找出最短路徑。

       Bellman-Ford首先會預測出從起點到各頂點之間最短距離的上限值,然後通過迭代運算的方式逐漸減少預測值和實際最短距離之間的誤差。而dijkstra演算法基於寬度優先搜尋,每次對某個頂點進行最短距離的計算。很顯然,兩種演算法具有完全不同的運算過程。Bellman-Ford在執行過程中會生成陣列upper[],該陣列將儲存起點到各頂點的最知距離的上限。隨著演算法的執行,此陣列當中的數值會慢慢變小,演算法結束時會會變成最短距離。

vector<int>  bellmanFord(int src) {
	vector<int>   upper(V, INF);
	upper[src] = 0;
	bool updated;
	//
	for (int iter=0; iter<V; iter++) {
		updated = false;
		for (int here=0; here<V; here++) {
			for (int i=0; i<adj[here].size(); i++) {
				int there = adj[here][i].first;
				int cost = adj[here][i].second;
				//
				if (upper[there] > upper[here] + cost) {
					upper[there] = upper[here] + cost;
					updated = true;
				}
			}
		}//
		if (!updated) break;
	}
	if (updated)   upper.clear();
	return upper;
}
三、弗洛伊德多源最短路徑演算法(Floyd):
     根據問題的需求,有時候需要對所有成對頂點求出最短距離。解決這種問題時,可以把各頂點都視為起點,並反覆執行dijkstra。若存在負權值,就改用bellman-ford。

其實,有一種更快的演算法Floyd,會計算出圖結構的所有成對頂點之間的最短距離,並儲存到二維陣列dist[][]。此陣列的元素dist[u][v]表示從頂點u到v的最短距離。


相關文章