Conscription
题目链接:
http://poj.org/problem?id=3723
解题思路:
把人看做顶点,关系看做边,这个问题就可以转化为求解无向图中最大权森林问题。最大权森林问题可以通过把所有边权取反之后
用最小生成树的算法求解。
AC代码:
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn = 50005;
struct Edge{
int u,v,cost;
}es[maxn];
int n,m,r;
int V;
int pa[maxn];
bool cmp(Edge a,Edge b){
return a.cost < b.cost;
}
int findset(int x){
if(x != pa[x])
pa[x] = findset(pa[x]);
return pa[x];
}
int kruskal(){
sort(es,es+r,cmp);
for(int i = 0; i <= V; i++)
pa[i] = i;
int i,u,v,cnt = V,sum = 0;
for(i = 0; i < r; i++)
{
u = findset(es[i].u);
v = findset(es[i].v);
if(u != v)
{
sum += es[i].cost;
pa[v] = u;
if(--cnt == 1)
break;
}
}
return sum;
}
int main(){
int T;
scanf("%d",&T);
while(T--){
scanf("%d%d%d",&n,&m,&r);
int x,y,d;
for(int i = 0; i < r; i++){
scanf("%d%d%d",&x,&y,&d);
es[i] = (Edge){x,n+y,-d};
}
V = n+m;
printf("%d\n",10000*(V)+kruskal());
}
return 0;
}