最小生成樹和最短路還是區別很大的,所以又雙叒來寫了。
最小生成樹問題顧名思義,概括來說就是路修的最短。
接下來引入幾個一看就明白的定義:
帶權圖:邊賦以權值的圖稱為網或帶權圖,帶權圖的生成樹也是帶權的,生成樹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號節點為起始...