最小生成樹(詳解)

2022-09-20 20:57:12 字數 3657 閱讀 1327

最小生成樹和最短路還是區別很大的,所以又雙叒來寫了。

最小生成樹問題顧名思義,概括來說就是路修的最短。

接下來引入幾個一看就明白的定義:

帶權圖:邊賦以權值的圖稱為網或帶權圖,帶權圖的生成樹也是帶權的,生成樹t各邊的權值總和稱為該樹的權。

最小生成樹(mst):權值最小的生成樹。

最小生成樹的性質:假設g=(v,e)是乙個連通網,u是頂點v的乙個非空子集。若(u,v)是一條具有最小權值的邊,其中u∈u,v∈v-u,則必存在一棵包含邊(u,v)的最小生成樹。

完成構造網的最小生成樹必須解決下面兩個問題:

(1)盡可能選取權值小的邊,但不能構成迴路;

(2)選取n-1條恰當的邊以連通n個頂點;

kruskal遠離更為簡單粗暴,但是需要借助並查集這一知識。

克魯斯卡爾演算法的基本思想是以邊為主導地位,始終選擇當前可用的最小邊權的邊(可以直接快排或者algorithm的sort)。每次選擇邊權最小的邊鏈結兩個端點是kruskal的規則,並實時判斷兩個點之間有沒有間接聯通。

現在我來模擬一下:

假如有以下幾個城市,之間都有相連的道路:

根據kruskal的原理,我們需要對邊權dis進行排序,每次找出最小的邊。

排序後,最小的邊自然是第8條邊,於是4和6相連。

遍歷繼續,第二小的邊是1號,1和2聯通。

再後來是邊3連線1,4。

dis也是14的還有邊5,它連線3,4。

其次是dis為15的邊4,但是2和4已經相連了,pass。

然後是dis為16的兩條邊(邊2和邊9),邊2連線1和3,邊9連線3和6,它們都已經間接相連,pass。

再然後就是dis為22的邊10,它連線5和6,5還沒有加入組織,所以使用這邊。繼續,發現此時已經連線了n-1條邊,結束,最後圖示如下:

給定乙個 n 個點 m 條邊的無向圖,圖中可能存在重邊和自

環,邊權可能為負數。

求最小生成樹的樹邊權重之和,如果最小生成樹不存在則輸出

impossible。

給定一張邊帶權的無向圖 g=(v,e),其中 v 表示圖中點的集

合,e 表示圖中邊的集合,n=|v|,m=|e|。

由 v 中的全部 n 個頂點和 e 中 n-1 條邊構成的無向連通子

圖被稱為 g 的一棵生成樹,其中邊的權值之和最小的生成樹

被稱為無向圖 g 的最小生成樹。

輸入格式

第一行包含兩個整數 n 和 m。

接下來 m 行,每行包含三個整數 u,v,w,表示點 u 和點 v

之間存在一條權值為 w 的邊。

輸出格式

共一行,若存在最小生成樹,則輸出乙個整數,表示最小生成

樹的樹邊權重之和,如果最小生成樹不存在則輸出 impossible。

資料範圍

1≤n≤105,

1≤m≤2*105,

圖中涉及邊的邊權的絕對值均不超過 1000。

輸入樣例:

4 51 2 1

1 3 2

1 4 3

2 3 2

3 4 4

輸出樣例:

6

#include #include #include using namespace std;

const int n = 100010, m = 200010, inf = 0x3f3f3f3f;

int n, m;

int p[n];

struct edge

}edges[m];

int find(int x)

int kruskal()

}if (cnt < n - 1) return inf;

return res;

}int main()

; }

int t = kruskal();

if (t == inf) puts("impossible");

else printf("%d\n", t);

return 0;

}

運算方法是任取乙個點,以這個點為集合開始,然後對所有點與這個點的距離進行更新,找出離這個集合最近的點,然後把這個點放進這個集合(所以每一次運算的時候都要判斷一下這個點是否在這個集合裡,所有要用到乙個vister陣列),然後再以這個集合繼續尋找離這個集合最近的點,直到沒有點存在。

給定乙個 n 個點 m 條邊的無向圖,圖中可能存在重邊和自

環,邊權可能為負數。

求最小生成樹的樹邊權重之和,如果最小生成樹不存在則輸出

impossible。

給定一張邊帶權的無向圖 g=(v,e),其中 v 表示圖中點的集

合,e 表示圖中邊的集合,n=|v|,m=|e|。

由 v 中的全部 n 個頂點和 e 中 n-1 條邊構成的無向連通子

圖被稱為 g 的一棵生成樹,其中邊的權值之和最小的生成樹

被稱為無向圖 g 的最小生成樹。

輸入格式

第一行包含兩個整數 n 和 m。

接下來 m 行,每行包含三個整數 u,v,w,表示點 u 和點 v

之間存在一條權值為 w 的邊。

輸出格式

共一行,若存在最小生成樹,則輸出乙個整數,表示最小生成

樹的樹邊權重之和,如果最小生成樹不存在則輸出 impossible。

資料範圍

1≤n≤500,

1≤m≤105,

圖中涉及邊的邊權的絕對值均不超過 10000。

輸入樣例:

4 51 2 1

1 3 2

1 4 3

2 3 2

3 4 4

輸出樣例:

6

#include #include #include using namespace std;

const int n = 510, inf = 0x3f3f3f3f;

int n, m;

int g[n][n];

int dist[n];

bool st[n];

int prim()

return res;

}int main()

int t = prim();

if (t == inf) puts("impossible");

else printf("%d\n", t);

return 0;

}

最小生成樹詳解

對於無向圖g v,e v 表示圖中的結點,e表示圖中的邊,所謂最小生成樹就是聯通圖 g中所有結點所需要的邊長度總和最小,這些邊加上 v就構成圖 g的一顆最小生成樹。這樣還不清楚我們可以舉個例子 有 n個城市分布在不同的地方,為了保證每個城市間都能用火車通行,我們需要在城市之間修鐵路,但是為了節約成本...

最小生成樹詳解

鏈式前向星 學習筆記 一 prim演算法 普通prim演算法模板 用前向星錄資料的時候記得把head初始化為 1 fill dist,dist len,max memset vis,0,sizeof vis int ans 0 dist 1 0 如果題目要求輸出最小生成樹,就把題目要求的源點s的di...

Prim演算法生成最小生成樹詳解

建立乙個low陣列代表相應每個節點連線所需最小費用,乙個vis陣列標記相應節點是否連線過。low陣列的初始值用節點1到其餘各點的費用來填充 如該圖所示low陣列的初始值應該為 0634 5以上便是1號節點對於其他各點的費用 接下來在low陣列中尋找最小值 為3號節點費用為3最小。接著以3號節點為起始...