最小生成樹——Kruscal(克魯斯卡爾算法)
阿新 • • 發佈:2019-03-31
else 一個 oot n) struct kruscal stream .html d+
一、核心思想
? 將輸入的數據由小到大進行排序,再使用並查集算法(傳送門)將每個點連接起來,同時求和。
? 個人認為這個算法比較偏向暴力,有些題可能會超時。
二、例題 洛谷—P3366
題目地址:https://www.luogu.org/problemnew/show/P3366
這是一道非常好的克魯斯卡爾算法的模板題。
題目描述
如題,給出一個無向圖,求出最小生成樹,如果該圖不連通,則輸出orz
輸入輸出格式
輸入格式:
第一行包含兩個整數N、M,表示該圖共有N個結點和M條無向邊。(N<=5000,M<=200000)
接下來M行每行包含三個整數Xi、Yi、Zi,表示有一條長度為Zi的無向邊連接結點Xi、Yi
輸出格式:
輸出包含一個數,即最小生成樹的各邊的長度之和;如果該圖不連通則輸出orz
輸入輸出樣例
輸入樣例:
4 5
1 2 2
1 3 2
1 4 3
2 3 4
3 4 3
輸出樣例:
7
AC代碼:
這段是符合題意的改良代碼,一開始我提交的時候沒有做orz的輸出,由於題的數據問題導致沒有設計orz也過了??????。
#include<iostream> #include<algorithm> #include<cstdio> using namespace std; int root[500000]; int book[500000]; int n, m; int ans; struct node { int be, en, dis; }road[500000]; bool cmp( node a, node b) { return a.dis < b.dis; } int findx( int a) { if (a == root[a]) return a; else return root[a] = findx(root[a]); } void mix( int a, int b) { int fr = findx(a), lr = findx(b); if(fr != lr) root[b] = fr; } int kruscal() { int sum = 0; int t1, t2; for( int i = 1; i <= m; i++) { t1 = findx(road[i].be); t2 = findx(road[i].en); if( t1 != t2) { sum += road[i].dis; ans++; mix(t1,t2); } if(ans == n-1) break; } return sum; } int main() { int sum; cin >> n >> m; for( int i = 1; i <= n; i++) root[i] = i; for( int i = 1; i <= m; i++) scanf("%d%d%d", &road[i].be, &road[i].en, &road[i].dis); sort( road+1, road+m+1, cmp); //對輸入的數據進行排序 sum = kruscal(); if(ans == n-1) cout << sum << endl; else cout << "orz" << endl; return 0; }
能力有限,有錯誤麻煩指出,萬分感謝。
最小生成樹——Kruscal(克魯斯卡爾算法)