您的位置:首页 > 其它

POJ 3723 conscription 最大生成树

2016-11-10 21:15 477 查看
F - Conscription
Time Limit:1000MS Memory Limit:65536KB 64bit IO Format:%lld
& %llu
Submit Status

Description

Windy has a country, and he wants to build an army to protect his country. He has picked up N girls and M 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 girl x 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.

Input

The first line of input is the number of test case.

The first line of each test case contains three integers, N, M and R.

Then R lines followed, each contains three integers xi, yi and di.

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

Output

For each test case output the answer in a single line.

Sample Input

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


Sample Output

71071
54223题目描述:要招n女,m男,每招一个人需要10000元,但是有一些男女有关系,代价为d,比如第i个女和第j个男有代价为d的关系,那么他们任意一个如果已经被招,则招另一个只需10000 - d元,问最少要用多少元招完这n女m男。思路:对于这个题我们可以设想一种关系,如果在招募士兵的过程中,有一对男女使用了关系d,那么我们就给他们连接一条边,就会得到一个无向图.最最需要注意的是在这个无向图中不可能存在回路,因为如果存在一个回路的话,无论从哪一个点开始适用这个关系都会矛盾,所以可以知道这是一个森林(故不一定都是连通的)所以我们可以把人看成一个顶点,关系d看做权值,问题求转化成了求最大权森林问题,求出最大权值森林权值的和,用(n+m)*10000-sum就可以得出结果;#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define M 100009
typedef struct edge
{
int u;
int v;
int w;
}edge;
int n,m,r;
int p[M];
edge e[M];
int ans;
int cmp(edge a,edge b)
{
return a.w > b.w;
}  //按最大权值排序;
int find(int x)
{
return x==p[x]? x: p[x]=find(p[x]);
}
void kruskal()
{
for(int i = 0;i < n+m;i++)
p[i] = i;
for(int i = 0;i < r;i++)
{
int x = find(e[i].u);
int y = find(e[i].v);
if(x!=y)
{
p[x] = y;
ans += e[i].w;
}
}

}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
ans = 0;
scanf("%d %d %d",&n,&m,&r);
for(int i = 0;i < r;i++)
{
int a,b,c;
scanf("%d %d %d",&a,&b,&c);
e[i].u=a;
e[i].v=b+n;//巧妙的将男女组合到一个数组当中,
e[i].w=c;
}
sort(e,e+r,cmp);
kruskal();
printf("%d\n",(n+m)*10000-ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  acm 图论