(最小生成树)Kruskal算法

            (最小生成树)Kruskal算法

  算法要点:Kruskal算法的最难点在于怎样判断加入边(x, y)后是否形成了环.

  问题可化简为:判断边(x, y)的两个顶点在图(实际是森林)mst中是否已连通。如果已经连通,加入边将形成环;

否则,不形成环。

  Kruskal算法中, 要用到并查集的合并与查找。

  完整代码如下:(具体见代码注释)

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int fa[1000010];
 4 int n, m;
 5 int sum = 0;
 6 struct node
 7 {
 8     int x, y;
 9     int v;
10 }e[10001000];
11 bool mycmp(node a, node b)
12 {
13     return a.v < b.v;
14 }
15 int getfa(int k)//找到祖先(最高级祖先) 
16 {
17     if(k == fa[k]) return k;
18     fa[k] = getfa(fa[k]);
19     return fa[k];
20 }
21 void merge(int x, int y)//合并x, y  
22 {
23     int fx = getfa(x);
24     int fy = getfa(y);
25     fa[x] = fy;
26 } 
27 bool judge(int x, int y)//判断是否在一个并查集中 
28 {
29     int fx = getfa(x);
30     int fy = getfa(y);
31     return (fx == fy);
32 }
33 int main()
34 {
35     //freopen("input.in","r",stdin);
36     //freopen("output.out","w",stdout);
37     scanf("%d%d",&n);
38     for(int i = 1;i < n;i++) 
39         scanf("%d%d%d", &e[i].x, &e[i].y, &e[i].v);
40     for(int i = 1; i <= n; i++)    fa[i] = i; //初始每个点都是一个集合
41     sort(e + 1, e + n + 1, mycmp); //边按升序排列
42     int cal = 0;
43     for(int i = 1;i <= n;i++)
44     {
45         int v = getfa(e[i].x);
46         int u = getfa(e[i].y);//寻找两个节点的祖先 
47         if(v != u)//如果不在一个并查集中 
48         {
49             merge(v, u);
50             sum += e[i].v;//最小生成树总长度 
51             if(++cal == n - 1)//如果已经做了N - 1次 
52             {
53                 printf("%d\n", sum);
54             }
55         } 
56     } 
57     return 0;
58 }

猜你喜欢

转载自www.cnblogs.com/smilke/p/10758196.html