簡介:最小生成樹算法一共有兩種,分別是kruskal算法和prim算法。也屬於貪心算法,它的目的就是給定無向圖、權值以及頂點,求聯通所有邊的權值和最小。
kruskal算法:
先構造一個只含 n 個頂點、而邊集爲空的子圖,把子圖中各個頂點看成各棵樹上的根結點,之後,從網的邊集 E 中選取一條權值最小的邊,若該條邊的兩個頂點分屬不同的樹,則將其加入子圖,即把兩棵樹合成一棵樹,反之,若該條邊的兩個頂點已落在同一棵樹上,則不可取,而應該取下一條權值最小的邊再試之。依次類推,直到森林中只有一棵樹,也即子圖中含有 n-1 條邊爲止。
這個算法實現就是先利用快排把從小到大排序,貪心算法取最優邊,然後利用並查集判斷兩邊是否已經在一個集合中。
核心代碼:
for(i=1;i<=m;i++)//開始從小到大枚舉每一條邊
{
if(merge(e[i].u,e[i].v))//利用並查集判斷兩個邊是否已經在一個集合中
{
count++;
sum=sum+e[i].w;
}
if(count==n-1)//到n-1條邊後退出循環
break;
}
prim算法:
算法流程:
1、從任意一個頂點構造生成樹,然後用book[]數組記錄標記的點。
2、用dis[]數組記錄生成樹到各個頂點的距離
3、從dis[]數組中選出離生成樹最近的頂點加入生成樹中,如果dis[k]>e[j][k],則重新更新dis[k]。
4、重複第三步,直到count==n.
核心代碼:
book[1]=1;//將1號頂點加入生成樹
count++;
while(count<n)
{
min=inf;
for(i=1;i<=n;i++)
{
if(book[i]==0&&dis[i]<min)
{
min=dis[i];
j=i;
}
}
book[j]=1;
count++;
sum+=dis[j];
for(k=1;k<=n;k++)//掃描當前j所在的頂點,再以j爲中間點,更新生成樹到每一個非樹頂點的位置
{
if(book[k]==0&&dis[k]>e[j][k])
dis[k]=e[j][k];
}
}