题目链接:点击打开链接
基础最小生成树
用克鲁斯卡尔算法,每一个有关系的男女间连一条边,权值为省的钱,算法执行排序时要从大到小排,求出的最大生成树就是可以省下的最大钱数,用总钱数去减这个就得到结果了。
代码:
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
int fa[20010];
struct seg{
int s,t,d;
}P[50010];
int Find(int n){
if(n==fa[n]) return n;
return fa[n]=Find(fa[n]);
}
bool same(int n,int m){
return Find(n)==Find(m);
}
void init(int num){
for(int i=0;i<=num;i++){
fa[i]=i;
}
}
void Union(int n,int m){
int p1=Find(n);
int p2=Find(m);
if(p1!=p2) fa[p1]=p2;
}
bool cmp(seg a,seg b){
return a.d>b.d;
}
int main(){
int T;
scanf("%d",&T);
while(T--){
int N,M,R;
scanf("%d%d%d",&N,&M,&R);
int num=N+M;
init(num);
for(int i=1;i<=R;i++){
scanf("%d%d%d",&P[i].s,&P[i].t,&P[i].d);
P[i].t+=N;
}
sort(P+1,P+R+1,cmp);
int sum=0;
for(int i=1;i<=R;i++){
if(!same(P[i].s,P[i].t)){
sum+=P[i].d;
Union(P[i].s,P[i].t);
}
}
printf("%d\n",num*10000-sum);
}
return 0;
}