关闭

poj3723(最大生成树)

标签: poj算法kruskal
78人阅读 评论(0) 收藏 举报
分类:

题目:点击打开链接

/*
translation:
	需要征兵女兵n人,男兵m人。征募每个人需要1w元,如果女兵x和男兵y有亲密度d。则一旦军队
	中有任意一方,则征募另外一方就可以减少d的费用。现在给出男女人数以及他们之间的亲密度,
	求征募完成所需的最少费用。

solution:
	kruskal,最大生成树。
	该题可以抽象成一个最大生成树模型。将每条边边值取负,就可求最小生成树了。之后将最小生成树的
	权值加上10000*(m+n),既是所求的答案!

note:
    并查集合并操作一定是将根合并的,一不留神容易写错。

date:
	2016.8.29
*/
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>

using namespace std;
const int maxn = 20001;

struct Edge {
	int from, to, d;
	Edge(int f_, int t_, int d_) : from(f_), to(t_), d(d_) {}
	bool operator < (const Edge &rhs) const {
		return d < rhs.d;	//从小到大
	}
};

int n, m, r;	//n girls, m boys, r relations
int pa[maxn];
vector<Edge> edges;

int get_root(int a) {
	if(pa[a] == a)	return a;
	pa[a] = get_root(pa[a]);
	return pa[a];
}

void Merge(int i, int j) {
	int r1 = get_root(i);
	int r2 = get_root(j);

	if(r1 == r2)	return;
	pa[r2] = r1;
}

int main()
{
    //freopen("in.txt", "r", stdin);
    int T;
    scanf("%d", &T);
    while(T--) {
		edges.clear();
		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);
			edges.push_back(Edge(x, y + n, -d));
		}

		sort(edges.begin(), edges.end());

		//kruskal
		for(int i = 0; i < n + m; i++)	pa[i] = i;
		int res = 0;
		for(int i = 0; i < r; i++) {
			Edge e = edges[i];
			if(get_root(e.from) != get_root(e.to)) {
				Merge(e.from, e.to);
				res += e.d;
			}
		}

		int ans = 10000 * (n+m) + res;
		printf("%d\n", ans);
    }
    return 0;
}


0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:36621次
    • 积分:2920
    • 等级:
    • 排名:第12612名
    • 原创:268篇
    • 转载:0篇
    • 译文:0篇
    • 评论:4条
    最新评论