什麼是生成樹
子圖:G=<V,E>,G'=<V', E'>,為兩個圖(V為點集,即圖中點的集合,E為邊集),如果V'是V的子集且E'是E的子集,則G'是G的子圖。
如果V'=V,則稱G'為G的生成子圖
如果G'是無向生成子圖且是樹的結構,則為生成樹
最小生成樹
最小生成樹:是一張有權無向連通圖中邊權和最小的生成樹
Prme演算法:
維護一個已經加入最小生成樹的點的集合C,每次通過一條邊連線一個不在這個點集C的點,直到最後形成一個樹形結構
Dist(u)表示u點到點集C中的點的最小距離
每次選擇一個到點集C距離最小的點加入點集C,並通過加入的點去更新未加入的點到點集C的最小距離(因為C中多加了一個點),直到n個點全部加入點集C或沒有點能夠加入(不能構成連通圖)。
圖解
前言:已經加入點集C的點標記為藍色,當前加入的點標記為紅色,被當前加入的點更新的dist標記為紅色。
初始:加入一個初始點A,並通過A更新dist
u | A | B | C | D | E | F |
dist(u) | 0 | 3 | 5 | inf | inf | inf |
加入第二個點B:B到點集C距離最小,並通過B更新dist
u | A | B | C | D | E | F |
dist(u) | 0 | 3 | 1 | 8 | 3 | inf |
加入第三個點C:C到點集C距離最小,並通過C更新dist
u | A | B | C | D | E | F |
dist(u) | 0 | 3 | 1 | 8 | 3 | inf |
加入第四個點E:E到點集C距離最小,並通過E更新dist
u | A | B | C | D | E | F |
dist(u) | 0 | 3 | 1 | 2 | 3 | 1 |
加入第五個點F:F到點集C距離最小,並通過F更新dist
u | A | B | C | D | E | F |
dist(u) | 0 | 3 | 1 | 2 | 3 | 1 |
加入第六個點D:D到點集C距離最小,並通過D更新dist
u | A | B | C | D | E | F |
dist(u) | 0 | 3 | 1 | 2 | 3 | 1 |
點全部加入點集,Prim演算法結束。
複雜度分析:
總共需要加入n個點,每次需要遍歷dist陣列找最小值,並通過該點更新未加入點集的dist值,即列舉該點連出的邊更新對應的dist,故複雜度為:
O(n*n)+ = O(n*n + m)(mi為每個點連出的邊的條數,總和為總邊數)
虛擬碼:
int prim()
{
memset(dis, 127, sizeof(dis)); //初始設定為正無窮
memset(vis, 0, sizeof(vis)); //初始設定點均不在點集中,點集為空
ans = 0, cnt = 0; //初始權值為0
dis[1] = 0; // 1加入點集
while (1)
{
int u = -1;
for (int i = 1; i <= n; i++)
{
if (vis[i] == 0 && dis[i] < (1 << 30)) // i點不在點集中並且與點集中的點聯通
{
if (u == -1 || dis[i] < dis[u]) // u==-1 ->第一個點可以更新到點集最近的點
{
u = i; //更新最近的點
}
}
}
if (u == -1)
break; //如果不能找到加入點集的點,則結束演算法
cnt++, ans += dis[u]; //點集中點的個數+1,ans加上u連入點集的邊權
vis[u] = true; // vis加入點集
for (auto it : a[u])//a[u]為以u連出的邊的點的集合,v為相連的點,w為邊權
{
dis[it.v] = min(dis[it.v], it.w); //通過點v連出的邊更新不在點集的點的dist值
}
}
if (cnt == n)
return ans; //能夠加入n個點構成連通圖,生成樹則返回權值
else
return -1; //不能形成生成樹
}
模板題
題目連結:
題目描述:
給你一張簡單無向連通圖,邊權都為非負整數。你需要求出它的最小生成樹,只需要輸出邊的權值和即可。
圖用以下形式給出:
第一行輸入兩個整數 n,m,表示圖的頂點數、邊數,頂點編號從 1 到 n。
接下來 m 行,每行三個整數 x,y,z 表示 x 與 y 之間有一條邊,邊權為 z。
輸入格式:
第一行兩個整數 n,m。
接下來 m 行,每行有三個整數,代表一條邊。
輸出格式:
輸出一個數,表示最小生成樹的權值和。
資料規模:
對於所有資料,保證 2≤n≤1000,n−1≤m≤100000,1≤x,y≤n,x≠y,1≤z≤10000
樣例輸入:
4 4
1 2 1
2 3 3
3 4 1
1 4 2
樣例輸出:
4
詳見程式碼:
參考文獻:
2022 Namomo Spring Camp Div2 Day10 直播課
ending
有什麼錯誤之處歡迎指正!不勝感激!