最小生成树--Boruvka算法
參考文章
介紹
第一次聽說這個(gè)算法。。
對于最小生成樹一定學(xué)過prim和krusal,prim復(fù)雜度是O(n2)或者O(elogn)O(n^2)或者O(elogn)O(n2)或者O(elogn),krusal復(fù)雜度是O(eloge)O(eloge)O(eloge),這里介紹一下Boruvka算法
Boruvka算法解決某些特定問題非常好用:
給定n個(gè)點(diǎn),每個(gè)點(diǎn)都有點(diǎn)權(quán),任意兩個(gè)點(diǎn)之間有邊權(quán),邊權(quán)為兩個(gè)點(diǎn)權(quán)用過某種計(jì)算方式得出(例如兩點(diǎn)權(quán)之差),求最小生成樹
點(diǎn)的數(shù)量為n,邊的數(shù)量為n^2,當(dāng)n=1e5,prim和Krusal都會超時(shí),現(xiàn)在用Boruvka求最小生成樹的算法:
考慮維護(hù)當(dāng)前的連通塊(初始每個(gè)點(diǎn)為獨(dú)立的一個(gè)連通塊)
對于每個(gè)連通塊,找到一條與該連通塊相連的,且另一端點(diǎn)不在此連通塊中的邊權(quán)最小的邊
將所有的這些邊加入到最小生成樹,注意,當(dāng)加入一個(gè)邊時(shí)需要判斷該點(diǎn)的兩端點(diǎn)是否在同一連通塊內(nèi)。
重復(fù)若干遍上述操作,直到圖連通
復(fù)雜度分析:每次連通塊的個(gè)數(shù)至少減半,復(fù)雜度為O((n+m)logn),并查集操作是O(1)
本算法不常用于求裸的最小生成樹(因?yàn)镵rusal更好用)
在給出的題目情況中,我們只需要求出每個(gè)連通塊相連的邊權(quán)的最小邊即可,在這種類型的題目中,這個(gè)東西的復(fù)雜度一般是O(nlogn)
所以可以在O(nlog2n)O(nlog^2n)O(nlog2n)的復(fù)雜度下解決此類問題
代碼:
#include <bits/stdc++.h> using namespace std; #define LL long long inline int read() {int x= 0;int w= 0;char ch= 0;while (ch < '0' || ch > '9')w|= ch == '-', ch= getchar();while (ch >= '0' && ch <= '9')x= (x << 3) + (x << 1) + (ch ^ 48), ch= getchar();return w ? (-x) : x; } #define mp make_pair const int N= 200005; const int M= 500005; const LL inf= 1e12; int f[N], pd, n, m; struct node {int a, b;LL c; } e[M]; pair<LL, LL> E[N]; int find(int k) {return (k == f[k]) ? k : f[k]= find(f[k]); } LL Boruvka() {LL res= 0;pd= 1;int num= 0;for (int i= 1; i <= n; i++)f[i]= i;while (num < n - 1) {int tmp= 0;for (int i= 1; i <= n; i++)E[find(i)]= mp(inf, inf);for (int i= 1; i <= m; i++) {int fa= find(e[i].a);int fb= find(e[i].b);if (fa == fb)continue;tmp++;//取最小的邊,最小邊一樣取最小編號 E[fa]= min(E[fa], mp(e[i].c, i * 1ll)); E[fb]= min(E[fb], mp(e[i].c, i * 1ll));}if (tmp == 0)break;for (int i= 1; i <= m; i++) {int fa= find(e[i].a);int fb= find(e[i].b);if (fa == fb)continue;if ((E[fa] == mp(e[i].c, i * 1ll)) || (E[fb] == mp(e[i].c, i * 1ll))) {f[fa]= fb;res+= e[i].c;num++;}}}if (num < n - 1)pd= 0;return res; } int main() {scanf("%d%d", &n, &m);for (int i= 1; i <= m; i++)scanf("%d%d%lld", &e[i].a, &e[i].b, &e[i].c);LL ans= Boruvka();if (!pd)printf("orz\n");elseprintf("%lld\n", ans);return 0; }題目:
CF1550F Jumping Around
總結(jié)
以上是生活随笔為你收集整理的最小生成树--Boruvka算法的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: excel中power函数的使用方法
- 下一篇: Gym102832K. Ragdoll(