最小生成樹
生成樹
現在一張有 個點的聯通無向圖
若 的一個子圖是一顆包含所有點的樹
則稱這顆樹爲原圖 的生成樹
簡單來說就是用 條邊將所有點連起來,這些邊所形成的便是原圖的生成樹
最小生成樹
如果把每條邊加上邊權,生成樹的 條邊的權值之和最小的被稱爲最小生成樹
舉個例子
其中的藍邊就是該圖的最小生成樹
最小生成樹算法
最常見的有Kruskal和Prim
由於Prim堆優化實在是不如Kruskal來的方便簡單,理解上也是Kruskal容易,所以直介紹Kruskal
Kruskal
生成樹既然是一棵樹,那麼肯定不存在迴路
這樣就可以把邊從小到大排序,之後依次循環往最小生成樹中加邊。
如果加入這條邊後樹中形成迴路,則不加此邊。
若樹中已含有 條邊便停止循環,這時的樹就是最小生成樹。
其中判斷迴路可以用並查集來實現。
加入一條邊 時
1. 如果 和 已經在同一個集合之中,便是形成迴路,不加此邊。
2. 否則增加此邊,將 , 合併。
主要代碼:
scanf("%d%d", &n, &m);
for(int i = 1; i <= m; i++)
scanf("%d%d%d", &edge[i].u, &edge[i].v, &edge[i].w);
sort(edge + 1, edge + m + 1);
for(int i = 1; i <= m; i++)
if(Union(edge[i].u, edge[i].v))
addedge(edge[i].u, edge[i].v, edge[i].w);