首先解釋什麼是最小生成樹,最小生成樹是指在一張圖中找出一棵樹,任意兩點的距離已經是最短的了。

演算法要點:

1、用book陣列存放訪問過的節點。

2、用dis陣列儲存對應下標的點到樹的最近距離,這裡要注意,是對樹最近的距離,而不是源點,這和單源最短路徑是有區別的。

3、用maps陣列儲存邊的關係。

4、每次先找到離樹最近的且沒有被訪問過的點,以這點的所有邊去更新dis陣列,也就是更新和樹的最近距離。

演算法模型:

for(迴圈n-1次,因為預設1點為起始點,已經被訪問了)

{

for(迴圈n次。)

{

利用book陣列,找到dis中的最近點,且沒被訪問過的點。

}

記錄該點被訪問,記錄當前dis該點的距離存放至答案。

for(迴圈n次)

{

利用book陣列,找到沒有被訪問過的點,用該點的所有邊更新dis陣列,也就是更新和樹的最近距離。

}

}

#include<cstdio>
#include<cstdlib>
#include<iostream> using namespace std;
/*最小生成樹Prim未優化版*/ int book[];//用於記錄這個點有沒有被訪問過
int dis[];//用於記錄距離樹的距離最短路程
int MAX = ;//邊界值
int maps[][];//用於記錄所有邊的關係 int main()
{
int i,j,k;//迴圈變數
int n,m;//輸入的N個點,和M條邊
int x,y,z;//輸入變數
int min,minIndex;
int sum=;//記錄最後的答案 cin>>n>>m; //初始化maps,除了自己到自己是0其他都是邊界值
for (i = ; i <= n; i++)
{
for (j = ; j <= n; j++)
{
if(i!=j)
maps[i][j] = MAX;
else
maps[i][j] = ;
}
} for (i = ; i <= m; i++)
{
cin>>x>>y>>z;//輸入的為無向圖
maps[x][y] = z;
maps[y][x] = z;
} //初始化距離陣列,預設先把離1點最近的找出來放好
for (i = ; i <= n; i++)
dis[i] = maps[][i]; book[]=;//記錄1已經被訪問過了 for (i = ; i <= n-; i++)//1已經訪問過了,所以迴圈n-1次
{
min = MAX;//對於最小值賦值,其實這裡也應該對minIndex進行賦值,但是我們承認這個圖一定有最小生成樹而且不存在兩條相同的邊
//尋找離樹最近的點
for (j = ; j <= n; j++)
{
if(book[j] == && dis[j] < min)
{
min = dis[j];
minIndex = j;
}
} //記錄這個點已經被訪問過了
book[minIndex] = ;
sum += dis[minIndex]; for (j = ; j <= n; j++)
{
//如果這點沒有被訪問過,而且這個點到任意一點的距離比現在到樹的距離近那麼更新
if(book[j] == && maps[minIndex][j] < dis[j])
dis[j] = maps[minIndex][j];
}
} cout<<sum<<endl;
} /* 6 9
2 4 11
3 5 13
4 6 3
5 6 4
2 3 6
4 5 7
1 2 1
3 4 9
1 3 2
Result:19 */

以上這個演算法是沒有優化過的,優化的方法很多,堆排序,鄰接表等等。有興趣可以繼續看看。

主要想說的是最小生成樹和單源最短路徑是有區別的,雖然看起來程式碼比較像,但是本質有些不同,看到題目的時候,還是要好好去分析使用什麼方法去做。