只是寫一個模板,具體講解就不講了,是一個並查集的應用+貪心的思想。
路徑壓縮還是很有用處的,沒有壓縮的時候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 }