• 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 }
  • 相关阅读:
    codevs1842 递归第一次
    codevs1501 二叉树最大宽度和高度
    (noi.openjudge.cn) 1.5编程基础之循环控制T36——T45
    (noi.openjudge.cn) 1.7编程基础之字符串T21——T30
    (noi.openjudge.cn) 1.9编程基础之顺序查找T06——T15
    (noi.openjudge.cn) 1.9编程基础之顺序查找T01——T05
    (noi.openjudge.cn) 1.7编程基础之字符串T31——T35
    (noi.openjudge.cn) 1.8编程基础之多维数组T21——T25
    Objective-C/C++混编编译器设置
    UITableView使用指南
  • 原文地址:https://www.cnblogs.com/douzujun/p/6421446.html
Copyright © 2020-2023  润新知