将问题转化为最小生成树,由于题目的权值是10000-权值,所以我将最小生成树kruskal算法稍微改下,就是将边按照从大到小排序,最后减去最大的生成树权值就行
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;
const int maxn = 50000 + 10;
int N,M, R,V;
int father[maxn];
struct edge
{
int u,v,cost;
} e[maxn];
bool cmp(edge a, edge b)
{
return a.cost > b.cost;
}
void init(int V)
{
for(int i = 0; i < V; i++) father[i] = i;
}
int Find(int x)
{
return x == father[x] ? x : father[x] = Find(father[x]);
}
bool same(int x, int y)
{
return Find(x) == Find(y);
}
void unite(int x, int y)
{
int fx = Find(x);
int fy = Find(y);
if(fx != fy) father[fx] = fy;
}
int kruskal()
{
int res = 0;
sort(e,e+R,cmp);
init(V);
for(int i = 0; i < R; i++)//R是边的个数
{
if(!same(e[i].u,e[i].v))
{
unite(e[i].u,e[i].v);
res += e[i].cost;
}
}
return res;
}
int main()
{
#ifdef xxz
freopen("in.txt","r",stdin);
#endif // xxz
int Case;
scanf("%d",&Case);
while(Case--)
{
scanf("%d%d%d",&N,&M,&R);
V = N + M;
for(int i = 0 ; i < R; i++)
{
scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].cost);
e[i].v += N;
}
printf("%d\n",10000*(N+M) - kruskal());
}
return 0;
}