最小生成树 克鲁斯卡尔(Kruskal)算法求最小生成树
算法 成功选择(n-1)条边后,形成一个棵最小生成树,当然如果算法无法选择出(n-1)条边,则说明原图不连通。
1 bool cmp(int i,int j) 2 { 3 return w[i]<w[j]; 4 } 5 sort(r,r+m,cmp);
然后我们需要考虑新加入的边会不会和先前选好的边形成环,即判断u,v,是否在同一连通分量中,这里我们用并查集来查找,然后合并
f[x]表示x的,合并只需条语句f[x]=y;。然后实现实现克鲁斯卡尔的算法的代码如下
1 #include<stdio.h> 2 #include<string.h> 3 #include<iostream> 4 #include<algorithm> 5 using namespace std; 6 #define maxn 5000 7 int f[maxn]; 8 int u[maxn],v[maxn],w[maxn],r[maxn]; 9 int n,m; 10 bool cmp(int i,int j) 11 { 12 return w[i]<w[j]; 13 } 14 int find(int x) 15 { 16 return f[x]==x?x:find(f[x]); 17 } 18 __int64 Kruskal() 19 { 20 __int64 ans=0; 21 for(int i=1;i<=n;i++) 22 { 23 f[i]=i; 24 } 25 for(int i=1;i<=m;i++) 26 { 27 r[i]=i; 28 } 29 sort(r+1,r+m+1,cmp); 30 for(int i=1;i<=m;i++) 31 { 32 int e=r[i]; 33 int x=find(u[e]); 34 int y=find(v[e]); 35 if(x!=y) 36 { 37 ans+=w[e]; 38 f[x]=y; 39 } 40 } 41 return ans; 42 } 43 int main() 44 { 45 while(~scanf("%d",&n)&&n) 46 { 47 memset(r,0,sizeof(r)); 48 //memset(u,0,sizeof(u)) 49 m=n*(n-1)/2; 50 for(int i=1;i<=m;i++) 51 { 52 scanf("%d %d %d",&u[i],&v[i],&w[i]); 53 } 54 printf("%lld\n",Kruskal()); 55 } 56 }