您的位置:首页 > 其它

poj 3723 Conscription 并查集+Kruskal 求最小生成树

2015-12-02 19:04 621 查看
题意:要招募n个需要征募女兵N人,男兵M人。每征募一个人需要花费10000美元。但是如果已经征募的人中有一些关系亲密的人,那么可以少花一点钱。题目中给你R个男女之间的亲密度关系,如果a号男和m号女有亲密度关系,那么只要现在招募到他们中的一个人,那么招募另外一个人的花费将变为10000-他们之间的亲密度。然后要求你求出招募到所有人的最小花费。

分析:可以求出最多可以减多少钱,用kruskal算法,把边从大到小排列。然后构造一颗最小生成树,用并查集判断是否在一个联通分支中,并且加到树中。因为男女都是从0开始编号,所以要重新编号

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int a[10000][10000];
int fa[20009];
struct point
{
int x,y,val;
}node[50005];
bool cmp(point p,point pp)
{
return p.val>pp.val;
}
int findfa(int x)
{
if(fa[x]!=x)fa[x]=findfa(fa[x]);
return fa[x];
}
int main()
{
int n,m,r;
int T;
scanf("%d",&T);
while(T--){
scanf("%d%d%d",&n,&m,&r);
for(int i=0;i<r;i++){
scanf("%d%d%d",&node[i].x,&node[i].y,&node[i].val);
node[i].y+=n;
}
sort(node,node+r,cmp);
int sum=0;
for(int i=0;i<n+m;i++)
fa[i]=i;
for(int i=0;i<r;i++){
int xx=findfa(node[i].x),yy=findfa(node[i].y);
if(xx!=yy){
fa[xx]=yy;
sum+=node[i].val;
}
}
printf("%d\n",(n+m)*10000-sum);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: