就是貪心加上並查集。html
先按邊權從小到大排個序,而後草1到m一條一條加邊,若這條邊相連的兩個節點沒有被連過,就將這兩個點所在的集合合併,這樣直到並查集的樹的邊加到 n - 1 。則最小生成樹各邊長度之和就是並查集各邊長度之和。ios
由於要記錄一條邊鏈接的哪兩個節點,因此開一個結構體,裏面a, b, c表明a和b之間鏈接着一條邊權爲c的邊。ide
上一道例題:https://www.luogu.org/problemnew/show/3366post
代碼spa
1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 using namespace std; 5 typedef long long ll; 6 struct Edge{ 7 int x, y; 8 ll z; 9 bool operator < (const Edge& other)const{ 10 return z < other.z; 11 }; 12 }edge[200005]; 13 int p[5005]; 14 void init() 15 { 16 for(int i = 1; i <= 5000; ++i) p[i] = i; 17 return; 18 } 19 int Find(int x) 20 { 21 return x == p[x] ? x : p[x] = Find(p[x]); 22 } 23 int merge(int a, int b) 24 { 25 int pa = Find(a), pb = Find(b); 26 if(pa == pb) return 0; 27 else 28 { 29 p[pa] = pb; 30 return 1; 31 } 32 } 33 int main() 34 { 35 init(); 36 int n, m, cnt = 0; 37 ll mst = 0; 38 scanf("%d%d", &n, &m); 39 for(int i = 1; i <= m; ++i) 40 { 41 scanf("%d%d%lld", &edge[i].x, &edge[i].y, &edge[i]. z); 42 } 43 sort(edge + 1, edge + m + 1); //從邊權小的邊開始加 44 for(int i = 1; i <= m; ++i) 45 { 46 if(merge(edge[i].x, edge[i].y) == 1) 47 { 48 cnt++; mst += edge[i].z; 49 } 50 if(cnt == n - 1) 51 { 52 printf("%lld\n", mst); 53 return 0; 54 } 55 } 56 printf("orz\n"); 57 return 0; 58 }