题意:
现在要雇佣n个男孩,m个女孩。然后有R个关系。雇佣每个人要花费10000RMB,然后如果某个男孩和女孩之间有一个关系d,那么选择这两个人之后就可以少交dRMB。每个人只能选择一个关系。
思路:每个人只能选择一个关系,这个很关键,也就是说每个点的父亲只有一个,所以说选完关系之后应该是一棵树。那么要使得折扣sumd最多,我们把权值改成负的表示折扣,就是求一棵最小生成树了。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <queue>
#include <stack>
using namespace std;
typedef long long LL;
const int MAXN = 1e4+5;
const int inf = 1e9;
int ng,nb,m;
int R;
struct edge
{
int u,v,w;
bool operator < (const edge &a)const
{
return w < a.w;
}
} edge[MAXN*5];
int pre[MAXN<<1];
int findx(int x)
{
return pre[x] == x?x:pre[x] = findx(pre[x]);
}
int kruskal()
{
for(int i = 0; i < R; ++i)pre[i] = i;
sort(edge,edge+m);
int ans = 0;
int cnt = 0;
for(int i = 0; i < m; ++i)
{
int u = edge[i].u;
int v = edge[i].v;
int w = edge[i].w;
u = findx(u);
v = findx(v);
if(u != v)
{
pre[v] = u;
cnt++;
ans += w;
if(cnt == R-1)return ans;
}
}
return ans;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d%d%d",&ng,&nb,&m);
R = ng + nb;
for(int i = 0; i < m; ++i)
{
scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].w);
edge[i].v += ng;
edge[i].w = -edge[i].w;
}
printf("%d\n",kruskal()+10000*R);
}
return 0;
}