zoukankan      html  css  js  c++  java
  • 最小生成树--模板

    板子:

     1 int V, E;
     2 int p[MAXN];
     3 int r[MAXN];
     4 
     5 void init(int n) {
     6     for (int i = 1; i <= n; i++) {
     7         p[i] = i, r[i] = 0;
     8     }
     9 }
    10 
    11 int find(int x) { return p[x] == x ? x : p[x] = find(p[x]); }
    12 
    13 bool same(int x, int y) { return find(x) == find(y); }
    14 
    15 void unite(int x, int y) {
    16     x = find(x);
    17     y = find(y);
    18     if (x == y) return;
    19     if (r[x] < r[y]) {
    20         p[x] = y;
    21     } else {
    22         p[y] = x;
    23         if (r[x] == r[y]) r[x]++;
    24     }
    25 }
    26 
    27 struct Edge {
    28     int u, v, cost;
    29 } edge[MAXM];
    30 bool cmp(const Edge& e1, const Edge& e2) { return e1.cost < e2.cost; }
    31 int Kruskal() {
    32     sort(edge + 1, edge + R + 1, cmp);
    33     init(V);
    34     int res = 0;
    35     for (int i = 1; i <= E; i++) {
    36         Edge e = edge[i];
    37         if (!same(e.u, e.v)) {
    38             unite(e.u, e.v);
    39             res += e.cost;
    40         }
    41     }
    42     return res;
    43 }

    题意:N个城堡,M个桥,每个桥的权值都不一样,题目要求能使城堡彼此联通的所有桥集合里面权值最小的那种,由此可以判断这是一道求最小生成树的题。

     1 #include<cstdio>
     2 #include<algorithm>
     3 using namespace std;
     4 typedef long long ll;
     5 
     6 const int maxn = 2000 + 5, maxm = 2e5 + 5;
     7 struct edge {
     8     int u, v, value;
     9 }myedge[maxm];
    10 int p[maxn], n, m;
    11 
    12 bool cmp(const edge&p1,const edge&p2) {
    13     return p1.value < p2.value;
    14 }
    15 
    16 int find(int x) {
    17     return (p[x] == x) ? x : (p[x] = find(p[x]));
    18 }
    19 
    20 int main() {
    21     scanf("%d%d", &n, &m);
    22     int a, b, id, k = 0;
    23     ll w;
    24     for (int i = 0; i < m; i++) {
    25         scanf("%d%d%lld%d", &a, &b, &w, &id);
    26         if (id == 1) {
    27             myedge[k].u = a;
    28             myedge[k].v = b;
    29             myedge[k].value = w;
    30             k++;
    31         }
    32     }
    33     if (k != 0) {
    34         for (int i = 0; i < n; i++) {
    35             p[i] = i;
    36         }
    37         sort(myedge, myedge + k, cmp);
    38         int x, y, counter = 0;
    39         ll value, sum = 0;
    40         for (int i = 0; i < k; i++) {
    41             value = myedge[i].value;
    42             x = find(myedge[i].u);
    43             y = find(myedge[i].v);
    44             if (x != y) {
    45                 sum += value;
    46                 p[y] = x;
    47                 counter++;
    48                 if (counter >= n - 1) break;
    49             }
    50         }
    51         printf("yes
    %lld
    ", sum);
    52     }
    53     else printf("no");
    54     return 0;
    55 }

    POJ3723

    题意:有 N 个男人 M 个女人,给出若干男女之间的 1~9999 之间的亲密度关系,征募某个人的费用是 10000 -(已经征募到的人中和自己的亲密度的最大值)。要求通过适当的征募顺序使得所有人的所需费用最小

    解法:把人与人看做点,则这个问题就转换为无向图中的最大权森林问题。将最小生成树中的边权去反即可用最小生成树的算法求解。

     1 int N, M, R;
     2 int p[MAXN];
     3 int r[MAXN];
     4 
     5 void init(int n) {
     6     for (int i = 1; i <= n; i++) {
     7         p[i] = i, r[i] = 0;
     8     }
     9 }
    10 
    11 int find(int x) { return p[x] == x ? x : p[x] = find(p[x]); }
    12 
    13 bool same(int x, int y) { return find(x) == find(y); }
    14 
    15 void unite(int x, int y) {
    16     x = find(x);
    17     y = find(y);
    18     if (x == y) return;
    19     if (r[x] < r[y]) {
    20         p[x] = y;
    21     } else {
    22         p[y] = x;
    23         if (r[x] == r[y]) r[x]++;
    24     }
    25 }
    26 
    27 struct Edge {
    28     int u, v, cost;
    29 } edge[MAXM];
    30 
    31 bool cmp(const Edge& e1, const Edge& e2) { return e1.cost < e2.cost; }
    32 
    33 LL Kruskal() {
    34     sort(edge + 1, edge + R + 1, cmp);
    35     init(N + M);
    36     LL res = 0;
    37     for (int i = 1; i <= R; i++) {
    38         Edge e = edge[i];
    39         if (!same(e.u, e.v)) {
    40             unite(e.u, e.v);
    41             res += e.cost;
    42         }
    43     }
    44     return res;
    45 }
    46 
    47 int main() {
    48     // freopen("input.txt", "r", stdin);
    49     int T;
    50     scanf("%d", &T);
    51     while (T--) {
    52         scanf("%d%d%d", &N, &M, &R);
    53         REP(i, 1, R) {
    54             scanf("%d%d%d", &edge[i].u, &edge[i].v, &edge[i].cost);
    55             edge[i].u++, edge[i].v++;
    56             edge[i].cost = 0 - edge[i].cost;
    57             edge[i].v = edge[i].v + N;
    58         }
    59         printf("%lld
    ", 10000 * 1ll * (N + M) + Kruskal());
    60     }
    61     return 0;
    62 }
  • 相关阅读:
    javaEE企业级基础介绍(一)
    SQL学习笔记系列(十)窗口函数
    SQL学习笔记系列(九)索引优化分析
    Tableau教程笔记
    淘宝用户行为分析--基于MySQL、Tableau
    Stop thinking,start living--《心灵奇旅》观后感
    SQL刷题
    SQL学习笔记系列(八)流程控制结构
    SQL学习笔记系列(七)存储过程和函数
    在超算系统上使用sbatch提交MXNet分布式训练任务
  • 原文地址:https://www.cnblogs.com/romaLzhih/p/9489829.html
Copyright © 2011-2022 走看看