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;
}