本题大体题意是:一个国王要招募士兵,现有男兵和女兵,招募一个需要10000元,但是如果一个男兵和一个女兵有关系d的话,在已经招募一个的情况下招募另一个只需花费10000-d即可。现在给出以下关系,问国王最少要花花多少钱。
最少花费就是求关系d的最大值,可以用最大生成树求,但最后不一定是一棵树,而是森林,所以需要用并查集判断二者是否已经被招募,只有在已招募情况下才能减去关系d的费用。最后要用总费用减去关系d的费用才是最小花费
#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
struct bian{
int v1,v2;
int w;
};
int n,m,r;
int f[50010];
bool cmp(const struct bian a,const struct bian b){
return a.w > b.w;
}
void init(){
for(int i = 0; i <= 50010; ++i) f[i] = i;
}
int getf(int a){
if(a == f[a]) return a;
return f[a] = getf(f[a]);
}
int merge(int a,int b){
int ta,tb;
ta = getf(a);
tb = getf(b);
if(ta == tb) return 0;
f[ta] = tb;
return 1;
}
int main()
{
int t;
int ans;
vector<struct bian> g;
scanf("%d",&t);
while(t--){
ans = 0;
g.clear();
init();
scanf("%d%d%d",&n,&m,&r);
for(int i = 0; i < r; ++i){
struct bian temp;
scanf("%d%d%d",&temp.v1,&temp.v2,&temp.w);
temp.v2 += n;
g.push_back(temp);
int tmp = temp.v1;
temp.v1 = temp.v2;
temp.v2 = tmp;
g.push_back(temp);
}
sort(g.begin(),g.end(),cmp);
for(int i = 0; i < (int)g.size(); ++i){
if(merge(g[i].v1,g[i].v2)){
ans += g[i].w;
}
}
printf("%d\n",((n+m)*10000 - ans));
}
return 0;
}