例題:
使用最小優先佇列將邊的權值進隊;然後依次出佇列。
並且用乙個一維資料記錄節點的父節點,出佇列的同時判斷兩個點的父節點是否相同,同則不用,不同則可以用。判斷是不是樹的時候,可以根據根節點判斷,因為每個節點中儲存的父節點都會間接指向根節點。
kruskal演算法
kruskal演算法也是採用貪心演算法的思想,執行時間為o(nlogn)。
演算法描述
設r是有n個頂點的對稱連通關係。s=是r的加權邊集合。
1)在s中選擇最小權的邊e1,設e = 用s- 取代s。
2)在s中選最小權的邊ei,並且不與e中的元素形成迴路。用e∪代替e,並用s- 取代s。
3)重複步驟知道|e|=n-1.
**設計
1、利用優先順序佇列將權值小的邊放到佇列最前,優先出對,保證了每次選擇的都是權值最小的邊。
2、利用並查集的查詢及結合把同處同一連通分量中的頂點連到同一父節點下。這樣,每次判斷是否構成迴路,只要判斷父節點是否相同的即可。
並查集
我們可以把每個連通分量看成乙個集合,該集合包含了連通分量的所有點。而具體的連通方式無關緊要,好比集合中的元素沒有先後順序之分,只有「屬於」與「不屬於」的區別。圖的所有連通分量可以用若干個不相交集合來表示。
而並查集的精妙之處在於用數來表示集合。如果把x的父結點儲存在p[x]中(如果沒有父親,p[x]=x),則不難寫出結點x所在樹的遞迴程式:
find(int x)
意思是,如果p[x]=x,說明x本身就是樹根,因此返回x;否則返回x的父親p[x]所在樹的根結點。
//**//
#include
using
namespace
std;
#define inf 0x3f3f3f3f
int minsum,point,side;//權值最小之和
int f[1100];
struct node;
priority_queueq;
bool
operator
< (const node& a, const node& b) //按照權值排列
int kruskal();
int find(int x);
bool judge();
int main()
minsum=kruskal ();
if(judge())
cout
cout
<
int kruskal ()
}for(int i=1;i<=point;i++)
f[i]=find(f[i]);//節點存進f[i]中
return minsum;
}int find(int x)//找點
bool judge()
} return
true;
}
Prim最小生成樹 優先佇列優化
處理何種問題 求解無向連通圖的最小生成樹,適合於稠密圖,即點少邊多的無向圖。效能 時間複雜度為 o v loge v為點的個數,e為邊的個數 原理 貪心策略。實現步驟 正向模擬找連線點。即取任意一點,放入集合,找此點集合內最短的邊且邊的另一端點不在該集合內的點,將改點放入點集合內,重複此操作,直至所...
最小生成樹 prim最小堆(優先佇列)優化演算法
基本prim最小生成樹 1 任意定點構樹 標記陣列標記入樹 2 初始化更新維護dis陣列 3 選出dis中最近的點j加入樹中,並以j為起點鬆弛 4.重複第3步選出n 1個點 堆優化prim最小生成樹 準備 dis陣列,p優先佇列,vis陣列記錄每個定點在最小堆中的位置 1.初始化優先佇列,以定義的起...
C 最小生成樹
樹是指沒有環路的圖,生成樹就是指乙個圖上面刪除一些邊,使它沒有環路。最小生成樹就是指生成樹中邊權之和最小的那一種。上圖的最小生成樹就是這樣 就以上圖為例 先選擇乙個起始點,我們就以a為例。建立乙個集合s,用來儲存已經在樹中間的點。開始時集合那只有點a,即 s 選擇乙個連通到集合s中乙個點的最小邊,其...