最小生成树--模板

板子:

 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 }
原文地址:https://www.cnblogs.com/romaLzhih/p/9489829.html