最小生成树Kruskal算法

     求最小生成树的算法——Kruskal

  • 思路 :先把所有的边排个序,然后枚举所有的边(从小到大),如果当前边所连的两个点并没有在同一个集合里(这一可以用并查集来实现)(需要判断两个点是否已经连通,如果已经连通了,那么再用这条边连一遍就没有什么意义了),就连上这条边了。如果已经连了n - 1条边(n - 1条边就可以将一个图变为一个连通图),就直接退出,如果到最后都没有连上n - 1条边,当前图则不连通。

  • 算法流程
  1. 输入所有的边,并将他们存在一个结构体中
  2. 以边权大小值进行从小到大的排序
  3. 设定一个记录一共连了多少条边的k和一个存最小生成树边权总和的ans
  4. 枚举所有边,如果已经连了n - 1条边就退出
  5. 如果当前边的两个端点没有在同一个集合里,就把它们连起来并且ans的值加上此边的边权,k也加一
  • 代码
 1 #include <bits/stdc++.h>
 2 #define INF 0x3f3f3f3f
 3 using namespace std;
 4 int n, m, v, k, ans, fa[1000001];
 5 struct node//定义结构体存图 
 6 {
 7     int x, y, z;//z表示x连y的权值 
 8 }stu[1000001];
 9 inline int find(int x)//并查集 
10 {
11     if(x != fa[x])
12     {
13         fa[x] = find(fa[x]);
14     }
15     return fa[x];
16 }//查找 
17 inline void unity(int x, int y)
18 {
19     int r1 = find(x);
20     int r2 = find(y);
21     fa[r1] = r2;
22     return;
23 }//合并 
24 inline int cmp(node a, node b)//从小到大结构体排序 
25 {
26     return a.z < b.z;
27 }
28 signed main()
29 {
30     scanf("%d %d", &n, &m);
31     for(register int i = 1; i <= n; ++i)
32     {
33         fa[i] = i;//并查集初始化 
34     }
35     for(register int i = 1; i <= m; ++i)
36     {
37         scanf("%d %d %d", &stu[i].x, &stu[i].y, &stu[i].z);
38     }
39     sort(stu + 1, stu + m + 1, cmp);//排序 
40     for(register int i = 1; i <= m; ++i)
41     {
42         if(find(stu[i].x) != find(stu[i].y))
43         {
44             ans += stu[i].z;//加上最小生成树中边的权值 
45             unity(stu[i].x, stu[i].y);//连接起来 
46             ++k;//记录边数 
47             if(k == n - 1)//n - 1条边就行了 
48             {
49                 printf("%d", ans);
50                 return 0;
51             }
52         }
53     }
54     return 0;
55 }

 

posted @ 2019-09-24 21:51  louis_11  阅读(250)  评论(0编辑  收藏  举报