克魯斯卡爾算法求最小生成樹


只是寫一個模板,具體講解就不講了,是一個並查集的應用+貪心的思想。

路徑壓縮還是很有用處的,沒有壓縮的時候tml了三個,壓縮之后明變快了不少,雖然還是那么慢

先說一下我的壓縮方法就當學習一下並查集:

 1 int Find(int x)
 2 {
 3     int r=x;
 4     while(fa[r]!=r)r=fa[r];
 5     while(x!=r){
 6         x=fa[x];
 7         fa[x]=r;
 8     }
 9     return fa[x];
10 }

非遞歸的路徑壓縮,先找到祖先結點,然后從頭到尾的更新路徑的每一個點,讓他們直接指向祖先結點

還有一種遞歸壓縮的,代碼不是很懂,可以去百度學習一下;

然后是最小生成樹代碼,用一個結構體存下每一條遍 的值和兩個節點,對遍從小到大排序,然后依次判斷兩個點是否在一個集合了,如果在就操作,如果不在就執行操作,執行N-1就完成了一棵最小生成樹

洛谷模板題3366:http://www.luogu.org/problem/show?pid=3366#sub

輸入格式:

第一行包含兩個整數N、M,表示該圖共有N個結點和M條無向邊。(N<=5000,M<=200000)

接下來M行每行包含三個整數Xi、Yi、Zi,表示有一條長度為Zi的無向邊連接結點Xi、Yi

輸出格式:

輸出包含一個數,即最小生成樹的各邊的長度之和;如果該圖不連通則輸出orz

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<string>
 5 using namespace std;
 6 #define MAX 200005
 7 struct NODE{
 8     int last ,next , val;
 9     }node[MAX];
10 
11 int fa[5005],M,N,ans=0;
12 
13 int Find(int x)
14 {
15     int r=x;
16     while(fa[r]!=r)r=fa[r];
17     while(x!=r){
18         x=fa[x];
19         fa[x]=r;
20     }
21     return fa[x];
22 }
23 
24 void work()
25 {
26     int s=0;
27     for(int i=1;i<=M;i++){
28         if(s==M-1)break;
29         int faa=Find( node[i].last );
30         int fbb=Find( node[i].next );
31         if( faa !=fbb ){
32             fa[faa]=fbb;
33             ans+=node[i].val;
34             s++;
35         }
36     }
37 }
38 
39 bool cmp(NODE A , NODE B)
40 {
41     return A.val<B.val;
42 }
43 
44 void init()
45 {
46     int i;
47     cin>>N>>M;
48     for( i=1;i<=M;i++){
49         cin>>node[i].last>>node[i].next>>node[i].val;
50     }
51     sort( node+1 , node+1+M , cmp );
52     for( i=1;i<=N;i++){
53         fa[i]=i;
54     }
55 }
56 
57 int main()
58 {
59     init();
60     work();
61     cout<<ans;
62     return 0;
63 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM