貪心-最短路徑問題

問題描述:

給定若干城市以及各城市之間的路線,求出到達每個城市的最短路徑。如下圖所示,各字母代表城市,有邊則代表城市之間連通,權值代表連通的城市之間的路徑值。

圖示:

在這裏插入圖片描述

Dijkstra求解:

1. Dijkstra思路分析

主要思想:通過構建的鄰接矩陣,更新源點到所有頂點的路徑。然後不斷藉助其他頂點更新源點到其他頂點的最短距離。
因此實現過程中,我們需要一個二維矩陣來保存各頂點間的連通關係。一個數組dist保存源點到達其他各頂點的距離。爲了區別已經藉助過的頂點和沒有藉助過的頂點,我們使用一個bool類型的數組保存各個頂點的使用關係。

2. 算法步驟
  1. 通過給定的各城市之間的連通關係,構建鄰接矩陣(初始狀態下,矩陣中各值爲無窮大)
  2. 通過給定的源點,構建dist[]、p[]數組以及集合s和v-s(通過bool類型數組保存,若頂點在s中,則對應數組值賦爲true)
  3. 在v-s中,尋找源點至其路徑最短的頂點,並且將找到的頂點加入到s集合中
  4. 判斷是否能借助上述找到的頂點,使到達其他頂點的路徑最短
  5. 若存在這樣的最短路徑,則更新dist[]和p[]數組
  6. 直至v-s集合爲空,表示已經找完了到達所有頂點的最短路徑
代碼示例:
#include<iostream>
using namespace std;

const int INT = 1e7;//定義無窮大 
const int N = 100;
int n, m, s;//定義城市個數/城市之間連線條數和源頂點
int map[N][N], dist[N], p[N];
bool flag[N];

void init_map(int map[N][N]){
 	for(int i = 0; i < N; i++){
  		for(int j = 0; j < N; j++)
   			map[i][j] = INT;
 	}
}
void dijkstra(int s){
 	for(int i = 1; i <= n; i++){//先初始化dist、p和集合s 
  		flag[i] = false;
  		dist[i] = map[s][i];
  		if(dist[i] != INT)
   			p[i] = s;
  		else 
   			p[i] = -1;
 	}
 	flag[s] = true;
 	dist[s] = 0;
 	int t = -1, min;//查找最短路徑 
 	for(int i = 1; i <= n; i++){
  		min = INT;
  		for(int j = 1; j <= n; j++){
   			if(!flag[j] && dist[j] < min){//查找V-S中路徑最小的頂點
    				min = dist[j];
   	 			t = j;
   			}
  		}
  		if(t == s) return;
  		flag[t] = true;
  		for(int j = 1; j <= n; j++){
   			if(!flag[j] && map[t][j] < INT){
    				if((dist[t] + map[t][j]) < dist[j]){
     					dist[j] = dist[t] + map[t][j];
     					p[j] = t;
    				} 
   			}
  		}
 	}
}

int main(){
 	init_map(map);
 	cin >> n >> m >> s;//城市個數/城市間連線條數/源頂點 
 	for(int i = 0; i < m; i++){//初始化鄰接矩陣 
  		int x, y, z;
  		cin >> x >> y >> z;
  		map[x][y] = z;
 	}
 	dijkstra(s);
 	for(int i = 1; i <= n; i++){
  		cout << "最短路徑爲:" << dist[i] << endl;
 	}
 	return 0;
} 
結果輸出:

在這裏插入圖片描述
參考文獻:《趣味算法》

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章