日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

最小生成树学习-Kruskal算法

發布時間:2025/4/9 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 最小生成树学习-Kruskal算法 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

轉載請注明來源

最小生成樹簡單的來說就是從無向連通圖的鄰接表或者鄰接矩陣中扣下來一棵權值最小的樹,他只有n-1條邊來連接n個頂點,并且不允許產生回路。

Kruskal算法首先要對邊進行排序,sort一遍升序即可。然后要進行的就是摳樹啦。最開始的時候把n個點看成獨立的n棵樹,然后按權值從小到大選擇邊,所選的邊連接的兩個頂點u,v應屬于兩顆不同的樹,則成為最小生成樹的一條邊,并將這兩顆樹合并作為一顆樹。?重復直到所有頂點都在一顆樹內或者有n-1條邊為止

求最小生成樹要用到之前學過的并查集

參考:https://blog.csdn.net/luoshixian099/article/details/51908175

下面貼上代碼

#include <bits/stdc++.h> #define fi first #define se second #define pb push_back #define fio ios::sync_with_stdio(false);cin.tie(0); #define pii pair<int,int> #define vi vector<int> #define vc vector<char> #define pi 3.1415926 #define ls l,m,rt<<1 #define rs m+1,r,rt<<1|1const int INF=0x3f3f3f3f; const int N=2e5+5;typedef long long ll; typedef double db; typedef unsigned long long ull; using namespace std;int n,m; int pre[N];struct edge {int start;int to;int value; }edges[N];void InitPre()//初始化pre數組 {for (int i=1;i<=n;i++){pre[i]=i;} }int findRoot(int n)//查找根節點 {int r=n;while(pre[r]!=r)//查找這個點的根節點 {r=pre[r];}//r現在是根節點int i=n,j;while(i!=r)//路徑壓縮,讓小弟直接歸老大直轄 {j=pre[i];pre[i]=r;i=j;}return r; }void join(int x,int y)//把各個連同分支連起來 {int r1=findRoot(x);int r2=findRoot(y);if(r1!=r2)//如果已經連通不用管 {pre[r1]=r2;//不連通的時候隨便指定一個是另一個的老大 } }bool cmp(edge a,edge b) {return a.value<=b.value; }void kruskal() {int sumValue=0;//生成樹的權值int cnt=0;//已用邊的數量int start,to,value;for (int i=1;i<=m;i++){start=edges[i].start;to=edges[i].to;if(findRoot(start)!=findRoot(to)){cout<<start<<"---"<<to<<" "<<edges[i].value<<endl;sumValue+=edges[i].value;cnt++;join(start,to);}if(cnt>=n-1) break;}cout<<"SumValue: "<<sumValue<<endl; }int main() {//n個點m條邊cin>>n>>m;InitPre();for (int i=1;i<=m;i++){cin>>edges[i].start>>edges[i].to>>edges[i].value;}sort(edges+1,edges+1+m,cmp);cout<<endl<<endl;kruskal(); }

測試數據

7 9 1 2 28 1 6 10 2 3 16 2 7 14 3 4 12 4 5 22 4 7 18 5 6 25 5 7 24

?--------------------------------------------------------------------

更新一波,這個板子在一些數據下面會T掉,可能某些方面寫的不好。。

重新貼一個

1 #include <bits/stdc++.h> 2 #define fi first 3 #define se second 4 #define pb push_back 5 #define fio ios::sync_with_stdio(false);cin.tie(0); 6 #define pii pair<int,int> 7 #define vi vector<int> 8 #define vc vector<char> 9 #define pi 3.1415926 10 #define ls l,m,rt<<1 11 #define rs m+1,r,rt<<1|1 12 13 const int INF=0x3f3f3f3f; 14 const int N=2e5+5; 15 16 typedef long long ll; 17 typedef double db; 18 typedef unsigned long long ull; 19 using namespace std; 20 struct Edge 21 { 22 int u,v,w; 23 }edge[200005]; 24 25 int fa[5005],n,m,ans,eu,ev,cnt; 26 inline bool cmp(Edge a,Edge b) 27 { 28 return a.w<b.w; 29 }//快排的依據 30 inline int findRoot(int x){ 31 while(x!=fa[x]) x=fa[x]=fa[fa[x]]; 32 return x; 33 } 34 inline void kruskal(){ 35 sort(edge,edge+m,cmp);//將邊的權值排序 36 for(int i=0;i<m;i++){ 37 eu=find(edge[i].u), ev=find(edge[i].v); 38 if(eu==ev) continue;//若出現環,則continue 39 ans+=edge[i].w;//更新答案 40 fa[ev]=eu; cnt++; 41 if(cnt==n-1) break;//循環結束條件 42 } 43 } 44 int main(){ 45 scanf("%d%d",&n,&m); 46 for(int i=1;i<=n;i++) fa[i]=i;//初始化并查集 47 for(int i=0;i<m;i++) 48 scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].w); 49 kruskal(); 50 printf("%d",ans); 51 return 0; 52 }

?

轉載于:https://www.cnblogs.com/TheSilverMoon/p/9309772.html

總結

以上是生活随笔為你收集整理的最小生成树学习-Kruskal算法的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。