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 }

 

posted @ 2017-02-20 09:55  douzujun  阅读(271)  评论(0编辑  收藏  举报