POJ - 3723 Conscription(最小生成树)
Posted sky-stars
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ - 3723 Conscription(最小生成树)相关的知识,希望对你有一定的参考价值。
Conscription
Descriptions
需要征募女兵N人,男兵M人。 每招募一个人需要花费10000美元。 如果已经招募的人中有一些关系亲密的人,那么可以少花一些钱。 给出若干男女之前的1 ~ 9999 之间的亲密度关系, 招募某个人的费用是 10000 - (已经招募了的人中和自己的亲密度的最大值)。 要求通过适当的招募顺序使得招募所有人所花费的费用最小。
Input
输入N, M, R;
接下来输入R行 (x, y, d) 表示第 x 号男兵和第 y 号女兵之间的亲密度是 d
Output
输入最小花费的值。
Sample Input
2
5 5 8
4 3 6831
1 3 4583
0 0 6592
0 1 3063
3 3 4975
1 3 2049
4 2 2104
2 2 7815 5 10
2 4 9820
3 2 6236
3 1 8864
2 4 8326
2 0 5156
2 0 1463
4 1 2439
0 4 4373
3 4 8889
2 4 3133
Sample Output
71071
54223
题目链接
https://vjudge.net/problem/POJ-3723
把人看成点,关系看作边,转化为求解无向图的最大权森林问题,这个问题又可以通过把所有边取反之后用最小生成树的算法求解
典型的kruskal算法
注意要用scanf printf
AC代码
#include <iostream> #include <cstdio> #include <fstream> #include <algorithm> #include <cmath> #include <deque> #include <vector> #include <queue> #include <string> #include <cstring> #include <map> #include <stack> #include <set> #include <sstream> #define IOS \ ios_base::sync_with_stdio(0); cin.tie(0); #define Mod 1000000007 #define eps 1e-6 #define ll long long #define INF 0x3f3f3f3f #define MEM(x, y) memset(x, y, sizeof(x)) #define Maxn 1000000 + 10 using namespace std; int N, M, R; int x[Maxn], y[Maxn], d[Maxn];//男孩 女孩 关系度 struct edge int u, v, cost;//u到v的距离为cost ; bool cmp(const edge &e1, const edge &e2)//从小到大排序 return e1.cost < e2.cost; edge es[Maxn]; int par[Maxn]; void init(int n)//初始化并查集 for (int i = 0; i <= n; i++) par[i] = i; int findr(int x)//寻根 if (par[x] == x) return x; return par[x] = findr(par[x]); void unite(int x, int y)//合并 x = findr(x); y = findr(y); if (x == y) return; par[x] = y; bool same(int x, int y)//判断根是否相同 return findr(x) == findr(y); int kruskal(int V, int E)//kruskal算法求最小生成树 sort(es, es + E, cmp); init(V); int res = 0; for (int i = 0; i < E; i++) edge e = es[i]; if (!same(e.u, e.v)) unite(e.u, e.v); res += e.cost; return res; int main() int T; scanf("%d", &T); while (T--)//T组测试样例 scanf("%d%d%d", &N, &M, &R);//存数据 for (int i = 0; i < R; i++) scanf("%d%d%d", &x[i], &y[i], &d[i]); int V, E; V = N + M;//顶点个数 E = R;//边个数 for (int i = 0; i < E; i++)//存入结构体 es[i] = (edge) x[i], N + y[i], -d[i]; printf("%d\n", 10000 * (N + M) + kruskal(V, E)); return 0;
以上是关于POJ - 3723 Conscription(最小生成树)的主要内容,如果未能解决你的问题,请参考以下文章