intさわだんのBlack History

刹那的レジェンドになりたい。

POJ 3723 Conscription

詳しくは蟻本p99参照

クラスカルやるだけ。

unionfindとkruskalなんも見ないで実装できたのでgood.

#include <cstdio>
#include <algorithm>

using namespace std;

const int MAX_N = 20003;
const int MAX_E = 50003;

int par[MAX_N];
int rank[MAX_N];
struct edge{int from,to,cost;};
int V,E;
edge es[MAX_E];

bool comp(const edge& e1,const edge& e2){
    return e1.cost < e2.cost;
}

void init(int n){
    for(int i = 0;i < n;i++){
	par[i] = i;
	rank[i] = 0;
    }
}

int find(int x){
    if(par[x] == x)return x;
    else{
	return par[x] = find(par[x]);
    }
}

void unite(int x,int y){
    x = find(x);
    y = find(y);

    if(x == y)return;

    if(rank[x] > rank[y]){
	par[y] = x;
    }else{
	par[x] = y;
	if(par[x] == par[y])rank[y]++;
    }
}

bool same(int x,int y){
    return (find(x) == find(y));
}


int kruskal(){

    init(V);
    sort(es,es + E,comp);

    int res = 0;

    for(int i = 0;i < E;i++){
	edge e = es[i];
	if(!same(e.from,e.to)){
	    res += e.cost;
	    unite(e.from,e.to);
	}
    }
    return res;
}

int main(){

    int t;
    scanf("%d",&t);

    while(t--){
	int n,m,r;
	scanf("%d%d%d",&n,&m,&r);

	V = n + m;
	E = r;

	for(int i = 0;i < r;i++){
	    int x,y,d;
	    scanf("%d%d%d",&x,&y,&d);
	    es[i] =(edge) {x,y+n,-d};
	}

	printf("%d\n",V*10000+kruskal());
    }
    return 0;
}