史上最全最小生成樹演算法

2022-05-07 20:15:09 字數 1677 閱讀 2686

我不信還有人比這個全

總共三種,大家最熟悉的\(kruskal\),\(prim\)以及不那麼熟悉的\(borůvka\)。

時間複雜度:\(kruskal:\mathcal(mlogm),prim:\mathcal(n^2),borůvka:\mathcal(mlogn)\)

堆優化\(prim\)可以到\(\mathcal(nlogn)\)。

實現過程:

\(kruskal:\)對所有邊排序,從小到大加入,如果會成環就不加入。

\(prim:\)任選乙個點加入最小生成樹點集\(v\)中,找到最小的一條邊\(e\),其一端在\(v\)中,一端不在,將這樣的邊加入最小生成樹中,重複上述操作即可。

\(borůvka\):開始每個點自成乙個聯通塊。 每次對所有聯通塊找一條邊權最小的邊(如果有邊權相同,就按編號取最小的編號),其中一端在該聯通塊內而另一端不在,接下來加入這些邊並合併聯通塊。 重複上述操作直到沒有聯通塊可以合併。

這是\(borůvka\)的動態演示,可以說是很清晰了。這個演算法就像是\(prim\)的高階版本對吧。。。

它的\(log\)是哪來的呢?實際上,它每次加邊合併之後聯通塊數會減少一半,所以總共只要進行\(log\)次。

上乙個總的**(堆優化\(prim\)用的是\(dijstra\)寫法)

#includeusing namespace std;

inline int read()

while(x!=eof&&x>='0'&&x<='9')

return w*f;

}const int n=5e3+10;

const int m=2e5+10;

namespace kruskal

lin[m];

inline bool cmp(line x,line y)

printf("%d",ans);

} inline int main() }

namespace priority_prime

lin[m];

int head[m],fa[n],vis[m],dis[n],min[m];

struct edge edge[m<<1];

inline void add(int from,int to,int dis)

priority_queue> q;

inline void priority_prime(int now)

printf("%d",ans);

} inline int main() }

namespace boruvka

lin[m];

inline int find(int x)

inline bool cmp(line x,line y)

inline bool check(int x,int y)

inline void boruvka()

for(int i=1;i<=n;i++)

if(min[i]&&!vis[min[i]])

} printf("%d",ans);

} inline int main() }

int main()

最小生成樹演算法

由帶權的連通圖生成的數的各邊加起來稱為生成樹的權,把權值最小的生成樹稱為最小生成樹 minimum spanning tree 簡稱為mst 構造最小生成樹的方法就是利用mst性質,一條一條地選擇可以加入的邊。下面介紹兩種用於構造最小生成樹的演算法,其中第一種演算法稱為prim演算法,第二種演算法稱...

最小生成樹演算法

乙個最簡單的最小生成樹 圖結構練習 最小生成樹 time limit 1000ms memory limit 65536k 有n個城市,其中有些城市之間可以修建公路,修建不同的公路費用是不同的。現在我們想知道,最少花多少錢修公路可以將所有的城市連在一起,使在任意一城市出發,可以到達其他任意的城市。輸...

演算法 最小生成樹

前言 最小生成樹是在乙個給定的無向圖中求一棵樹,這棵樹包含無向圖中的所有頂點,且樹中的邊都來自無向圖中的邊,並且要滿足整棵樹的邊權之和最小。1 最小生成樹是樹,其邊數等於頂點數減1,且不會有環 2 對於給定的圖最小生成樹可以不唯一,但是邊權之和一定是唯一的。3 其根節點可以是這棵樹上的任何乙個節點,...