Prim算法:用來解決最小生成樹的問題
Prim算法和Dijkstra算法思想類似,都是採用貪心的思想。
兩個算法的主要區別:
-
Dijkstra算法的dis[]數組是記錄未訪問結點集合與源結點的最短路徑,而Prim算法的dis[]數組記錄的是未訪問結點集合到已訪問結點結合的最短距離。
兩個算法都是用bool visited[]數組來表示當前結點是否被訪問。 -
Prim算法有一個統計最小生成樹的總的最短距離len,每次訪問一個距離最短的結點,都要將該最短邊加上len,而Dijkstra算法則沒有該變量。
-
Prim算法是求解最小生成樹的算法,比如用來求解N個村莊之間修路的最小花費,而Dijkstra算法是求解單源最短路徑的算法,比如求解某一個村莊到所有村莊的最短路徑。
算法的具體步驟:
1、除了指定根結點外,其他的結點的dis[]都設置爲INF(無窮大)
2、遍歷n次,n爲圖中的結點數。每次都找出未被訪問結點距離已訪問結點集合的最小值。
3、遍歷當前結點所鄰接的未被訪問的邊,如果以當前結點作爲中介點,使得其鄰接點到已訪問集合的距離更短。則更新距離。
樣例:
輸入:
6 10//6個頂點,10條邊。以下10行爲10條邊
0 1 4//邊0->1與1->0的邊權爲4,下同
0 4 1
0 5 2
1 2 6
1 5 3
2 3 6
2 5 5
3 4 4
3 5 5
4 5 3
輸出:
15
下面爲實現代碼:
#include <iostream>
#include <algorithm>
using namespace std;
const int prim_max_num = 1000;
const int INF = 1000000000;
int n, m, G[prim_max_num][prim_max_num];
int dis[prim_max_num]; //頂點與集合S的最短距離
bool visited[prim_max_num] = {false};
//求出最小生成樹的最短距離
int prim()
{
//默認根結點爲 0
fill(dis, dis + prim_max_num, INF); //初始化 dis 數組
dis[0] = 0;
int result = 0;
for (int i = 0; i < n; i++)
{ //共有 n 個結點
int index = -1; //最短路徑結點的下標
int min = INF;
for (int j = 0; j < n; j++)
{
if (visited[j] == false && dis[j] < min)
{
index = j;
min = dis[j];
}
}
//找不到最小結點
if (index == -1)
{
return -1;
}
visited[index] = true;
result += dis[index];
for (int k = 0; k < n; k++)
{
if (visited[k] == false && G[index][k] != INF && G[index][k] < dis[k])
{
dis[k] = G[index][k];
}
}
}
return result;
}
int main()
{
cin >> n >> m;
fill(G[0], G[0] + prim_max_num * prim_max_num, INF);
int from_node, to_node, weight;
for (int i = 0; i < m; i++)
{
cin >> from_node >> to_node >> weight;
G[from_node][to_node] = G[to_node][from_node] = weight;
}
int result = prim();
cout << result << endl;//輸出最短距離
system("pause");
return 0;
}
運行結果: