Windy has a country, and he wants to build an army to protect his country. He has picked upN girls andM boys and wants to collect them to be his soldiers. To collect a soldier without any privilege, he must pay 10000 RMB. There are some relationships between girls and boys and Windy can use these relationships to reduce his cost. If girlx and boy y have a relationship d and one of them has been collected, Windy can collect the other one with 10000-d RMB. Now given all the relationships between girls and boys, your assignment is to find the least amount of money Windy has to pay. Notice that only one relationship can be used when collecting one soldier.
The first line of input is the number of test case.
The first line of each test case contains three integers, N, M andR.
Then R lines followed, each contains three integers xi,yi anddi.
There is a blank line before each test case.
1 ≤ N, M ≤ 10000
0 ≤ R ≤ 50,000
0 ≤ xi < N
0 ≤ yi < M
0 < di < 10000
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 781 5 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
71071 54223
一共要招募n+m个士兵,原则上每招募一个士兵要花费10000元,
但是假如在已经招募的士兵中存在与他关系亲密的人,那么就可以少花点钱,
这种关系对一个士兵最多只能用一次,问最少可以花费多少钱把士兵招募齐。
本题的难点就是如何将男女的放在一个组里来讨论,因为目前他们的编号可能一样
而且关系是男女之间的关系
一个巧妙的方法是把男士兵或者女士兵的编号加MAX
即0----MAX-1 表示女生 MAX-----MAX+n 表示男生
本题用sort快排超时,我们可以用优先队列来处理数据,大大节省了时间
代码:
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<queue>
#define MAX 10005
using namespace std;
struct node{
int B; //男孩编号,要特殊处理,将编号+MAX,防止与女孩编号重复
int G; //女孩编号
int cost;//可以省下的花费
}num[MAX];
int pre[MAX*3];
int n,m,k;
void init(){//初始化pre数组
int i;
for(i=0;i<=n+MAX+m;i++){//
pre[i]=i;
}
}
int Find(int x){
int r=x;
while(r!=pre[r]) //寻找根结点
r=pre[r];
int i=x,j;
while(i!=r){ //路径压缩
j=pre[i];
pre[i]=r;
i=j;
}
return r;
}
int mix(int a,int b){
int fa=Find(a),fb=Find(b);
if(fa!=fb){
pre[fb]=fa;
return 1;
}
return 0;
}
int operator<(node a,node b){ //重载函数
return a.cost<b.cost;
}
int main(){
int T;
scanf("%d",&T);
while(T--){
memset(pre,0,sizeof(pre));
memset(num,0,sizeof(num));
scanf("%d%d%d",&n,&m,&k);
init();
priority_queue<node>p;
int i;
for(i=0;i<k;i++){
int a,b,d;
scanf("%d%d%d",&a,&b,&d);
node temp;
temp.B=a+MAX;
temp.G=b;
temp.cost=d;
p.push(temp);
}
int cnt=0;
int sum=0;
while(!p.empty()){
node temp=p.top();
p.pop();
if(mix(temp.B,temp.G)){
cnt++;
sum+=temp.cost;
}
if(cnt==(n+m-1)) break; //树的边数比点数少一
}
printf("%d\n",(n+m)*10000-sum);
}
return 0;
}