kruskal算法:POJ No.3723 Conscription_最小生成树应用_最大权森林

  1 #define _CRT_SECURE_NO_WARNINGS
  2 /*
  3  5 5 8
  4  4 3 6831
  5  1 3 4583
  6  0 0 6592
  7  0 1 3063
  8  3 3 4975
  9  1 3 2049
 10  4 2 2104
 11  2 2 781
 12 */
 13 #include <iostream>
 14 #include <vector>
 15 #include <algorithm>
 16 #include <cstdio>
 17 using namespace std;
 18 
 19 const int maxn = 10000 + 10;
 20 const int maxR = 50000;
 21 const int INF = 9999999;
 22 int par[maxn];     //父亲,  当par[x] = x时,x是所在的树的根
 23 int Rank[maxn];    //树的高度
 24 int N, M, R;
 25 int V, E;
 26 int x[maxR], y[maxR], d[maxR];
 27 
 28 struct edge
 29 {
 30     int u, v, cost;
 31     edge(int u = 0, int v = 0, int cost = 0) : u(u), v(v), cost(cost) {}
 32 };
 33 
 34 bool comp(const edge& e1, const edge& e2) {
 35     return e1.cost < e2.cost;
 36 }
 37 
 38 edge es[maxn];
 39 
 40 //并查集实现-高效的判断是否属于同一个连通分量。
 41 void init_union_find(int n);
 42 int find(int x);
 43 void unite(int x, int y);
 44 bool same(int x, int y);
 45 
 46 //最小生成树
 47 void input();
 48 int kruskal();   //最小生成树算法
 49 //最大权森林
 50 void solve();
 51 
 52 //初始化n个元素
 53 void init_union_find(int n)
 54 {
 55     for (int i = 0; i < n; i++) {
 56         par[i] = i;
 57         Rank[i] = 0;
 58     }
 59 }
 60 
 61 //查询树的根
 62 int find(int x) {
 63     if (par[x] == x) {
 64         return x;
 65     }
 66     else {
 67         return par[x] = find(par[x]);
 68     }
 69 }
 70 
 71 //合并x和y所属集合
 72 void unite(int x, int y) {
 73     x = find(x);
 74     y = find(y);
 75     if (x == y) return;
 76 
 77     if (Rank[x] < Rank[y]) {
 78         par[x] = y;
 79     }
 80     else {
 81         par[y] = x;
 82         if (Rank[x] == Rank[y]) Rank[x]++;    //如果x,y的树高相同,就让x的树高+1
 83     }
 84 }
 85 
 86 //判断x和y是否属于同一个集合
 87 bool same(int x, int y) {
 88     return find(x) == find(y);
 89 }
 90 
 91 void input()
 92 {
 93     scanf("%d%d%d", &N, &M, &R);
 94     for (int i = 0; i < R; i++) {
 95         scanf("%d%d%d", &x[i], &y[i], &d[i]);
 96     }
 97 }
 98 
 99 int kruskal()
100 {
101     sort(es, es + E, comp); //按照edge.cost的顺序从小到大排序
102     init_union_find(V);     //将并查集初始化
103     int res = 0;
104     for (int i = 0; i < E; i++) {
105         edge e = es[i];
106         if (!same(e.u, e.v)) {
107             unite(e.u, e.v);
108             res += e.cost;
109         }
110     }
111     return res;
112 }
113 
114 void solve()
115 {
116     V = N + M;
117     E = R;
118     for (int i = 0; i < R; i++) {
119         es[i] = edge(x[i], N + y[i], -d[i]);
120     }
121     int res = kruskal();                    
122     //cout << "Debug" << res << endl;
123     cout << 10000 * (N + M) + res << endl;  //kruskal结果是-d[i]
124 }
125 
126 int main()
127 {
128     input();
129     solve();
130     return 0;
131 }
原文地址:https://www.cnblogs.com/douzujun/p/6421446.html