(1) 将全部边按照权值由小到大排序。 (2) 按顺序(边权由小到大的顺序)考虑没条边,只要这条边和我们已经选择的边步构成圈,就保留这条边,否则放弃这条边。
算法 成功选择(n-1)条边后,形成一个棵最小生成树,当然如果算法无法选择出(n-1)条边,则说明原图不连通。
算法 成功选择(n-1)条边后,形成一个棵最小生成树,当然如果算法无法选择出(n-1)条边,则说明原图不连通。
图中的路径按照权值的大小的排序为
AF 1;
BE 4;
BD 5;
BC 6;
DC:10;
BF 11;
DF 14;
AE 16;
AB 17;
EF 33;
算法的处理过程如下
先选A,F不在一个集合中,所以选AF。
E,D不在一个一个集合中,可以选
B,D不在一个集合中,可选BD
B,C不在一个集合中,可选BC
B,D在同一个集合中,放弃BD,
选BF
至此所有的的顶点都连起来,算法结束= =
;u[i],v[i]分别储存顶点,w[i]保存权值,用r[i]表示边的序号
这里对权值的排序可以这样写
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;。然后实现实现克鲁斯卡尔的算法的代码如下
#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 }