Prim算法html
1.概覽算法
普里姆算法(Prim算法),圖論中的一種算法,可在加權連通圖裏搜索最小生成樹。意即由此算法搜索到的邊子集所構成的樹中,不但包括了連通圖裏的全部頂點,且其全部邊的權值之和亦爲最小。該算法於1930年由捷克數學家沃伊捷赫·亞爾尼克發現;並在1957年由美國計算機科學家羅伯特·普里姆獨立發現;1959年,艾茲格·迪科斯徹再次發現了該算法。所以,在某些場合,普里姆算法又被稱爲DJP算法、亞爾尼克算法或普里姆-亞爾尼克算法。spa
2.算法簡單描述xml
1).輸入:一個加權連通圖,其中頂點集合爲V,邊集合爲E;htm
2).初始化:Vnew = {x},其中x爲集合V中的任一節點(起始點),Enew = {},爲空;blog
3).重複下列操做,直到Vnew = V:ci
a.在集合E中選取權值最小的邊<u, v>,其中u爲集合Vnew中的元素,而v不在Vnew集合當中,而且v∈V(若是存在有多條知足前述條件即具備相同權值的邊,則可任意選取其中之一);數學
b.將v加入集合Vnew中,將<u, v>邊加入集合Enew中;it
4).輸出:使用集合Vnew和Enew來描述所獲得的最小生成樹。table
下面對算法的圖例描述
圖例 | 說明 | 不可選 | 可選 | 已選(Vnew) |
---|---|---|---|---|
|
此爲原始的加權連通圖。每條邊一側的數字表明其權值。 | - | - | - |
|
頂點D被任意選爲起始點。頂點A、B、E和F經過單條邊與D相連。A是距離D最近的頂點,所以將A及對應邊AD以高亮表示。 | C, G | A, B, E, F | D |
|
下一個頂點爲距離D或A最近的頂點。B距D爲9,距A爲7,E爲15,F爲6。所以,F距D或A最近,所以將頂點F與相應邊DF以高亮表示。 | C, G | B, E, F | A, D |
![]() |
算法繼續重複上面的步驟。距離A爲7的頂點B被高亮表示。 | C | B, E, G | A, D, F |
|
在當前狀況下,能夠在C、E與G間進行選擇。C距B爲8,E距B爲7,G距F爲11。E最近,所以將頂點E與相應邊BE高亮表示。 | 無 | C, E, G | A, D, F, B |
|
這裏,可供選擇的頂點只有C和G。C距E爲5,G距E爲9,故選取C,並與邊EC一同高亮表示。 | 無 | C, G | A, D, F, B, E |
|
頂點G是惟一剩下的頂點,它距F爲11,距E爲9,E最近,故高亮表示G及相應邊EG。 | 無 | G | A, D, F, B, E, C |
|
如今,全部頂點均已被選取,圖中綠色部分即爲連通圖的最小生成樹。在此例中,最小生成樹的權值之和爲39。 | 無 | 無 | A, D, F, B, E, C, G |
3.簡單證實prim算法
反證法:假設prim生成的不是最小生成樹
1).設prim生成的樹爲G0
2).假設存在Gmin使得cost(Gmin)<cost(G0) 則在Gmin中存在<u,v>不屬於G0
3).將<u,v>加入G0中可得一個環,且<u,v>不是該環的最長邊(這是由於<u,v>∈Gmin)
4).這與prim每次生成最短邊矛盾
5).故假設不成立,命題得證.
#define MAX 100000
#define VNUM 10+1 //這裏沒有ID爲0的點,so id號範圍1~10
int edge[VNUM][VNUM]={/*輸入的鄰接矩陣*/};
int lowcost[VNUM]={0}; //記錄Vnew中每一個點到V中鄰接點的最短邊
int addvnew[VNUM]; //標記某點是否加入Vnew
int adjecent[VNUM]={0}; //記錄V中與Vnew最鄰近的點
void prim(int start)
{
int sumweight=0;
int i,j,k=0;
for(i=1;i<VNUM;i++) //頂點是從1開始
{
lowcost[i]=edge[start][i];
addvnew[i]=-1; //將全部點至於Vnew以外,V以內,這裏只要對應的爲-1,就表示在Vnew以外
}
addvnew[start]=0; //將起始點start加入Vnew
adjecent[start]=start;
for(i=1;i<VNUM-1;i++)
{
int min=MAX;
int v=-1;
for(j=1;j<VNUM;j++)
{
if(addvnew[j]!=-1&&lowcost[j]<min) //在Vnew以外尋找最短路徑
{
min=lowcost[j];
v=j;
}
}
if(v!=-1)
{
printf("%d %d %d\n",adjecent[v],v,lowcost[v]);
addvnew[v]=0; //將v加Vnew中
sumweight+=lowcost[v]; //計算路徑長度之和
for(j=1;j<VNUM;j++)
{
if(addvnew[j]==-1&&edge[v][j]<lowcost[j])
{
lowcost[j]=edge[v][j]; //此時v點加入Vnew 須要更新lowcost
adjecent[j]=v;
}
}
}
}
printf("the minmum weight is %d",sumweight);
}
轉: http://www.cnblogs.com/biyeymyhjob/archive/2012/07/30/2615542.html