Kruskal算法:最小生成树
//Kruskal算法按照边的权值从小到大查看一遍,如果不产生圈(重边等也算在内),就把当前这条表加入到生成树中。
//如果判断是否产生圈。假设现在要把连接顶点u和顶点v的边e加入生成树中。如果加入之前的u和v不在同一个连通分量里,那么加入e也不会产生圈。
//反之,如果u和v在同一个连通分量里,那一定会产生圈。可以用并查集高效判断是否属于同一个连通分量。
1 #define _CRT_SECURE_NO_WARNINGS
2 /*
3 7 10
4 0 1 5
5 0 2 2
6 1 2 4
7 1 3 2
8 2 3 6
9 2 4 10
10 3 5 1
11 4 5 3
12 4 6 5
13 5 6 9
14 */
15 #include <iostream>
16 #include <vector>
17 #include <algorithm>
18 using namespace std;
19
20 const int maxn = 1010 + 10;
21 const int INF = 9999999;
22 int par[maxn]; //父亲, 当par[x] = x时,x是所在的树的根
23 int Rank[maxn]; //树的高度
24 struct edge
25 {
26 int u, v, cost;
27 };
28
29 bool comp(const edge& e1, const edge& e2) {
30 return e1.cost < e2.cost;
31 }
32
33 edge es[maxn];
34 int V, E; //顶点数和边数
35 //并查集实现-高效的判断是否属于同一个连通分量。
36 void init_union_find(int n);
37 int find(int x);
38 void unite(int x, int y);
39 bool same(int x, int y);
40 void init();
41 void input();
42 int kruskal(); //最小生成树算法
43
44 //初始化n个元素
45 void init_union_find(int n)
46 {
47 for (int i = 0; i < n; i++) {
48 par[i] = i;
49 Rank[i] = 0;
50 }
51 }
52
53 //查询树的根
54 int find(int x) {
55 if (par[x] == x) {
56 return x;
57 }
58 else {
59 return par[x] = find(par[x]);
60 }
61 }
62
63 //合并x和y所属集合
64 void unite(int x, int y) {
65 x = find(x);
66 y = find(y);
67 if (x == y) return;
68
69 if (Rank[x] < Rank[y]) {
70 par[x] = y;
71 }
72 else {
73 par[y] = x;
74 if (Rank[x] == Rank[y]) Rank[x]++; //如果x,y的树高相同,就让x的树高+1
75 }
76 }
77
78 //判断x和y是否属于同一个集合
79 bool same(int x, int y) {
80 return find(x) == find(y);
81 }
82
83 void init() {
84
85 }
86
87 void input()
88 {
89 edge tmp;
90 for (int i = 0; i < E; i++) {
91 cin >> tmp.u >> tmp.v >> tmp.cost;
92 es[i] = tmp;
93 }
94 }
95
96 int kruskal()
97 {
98 sort(es, es + E, comp); //按照edge.cost的顺序从小到大排序
99 init_union_find(V); //将并查集初始化
100 int res = 0;
101 for (int i = 0; i < E; i++) {
102 edge e = es[i];
103 if (!same(e.u, e.v)) {
104 unite(e.u, e.v);
105 res += e.cost;
106 }
107 }
108 return res;
109 }
110
111 int main()
112 {
113 cin >> V >> E;
114 input();
115 int res = kruskal();
116 cout << res << endl;
117 return 0;
118 }