首页 > 其他 > 详细

fzu 1963 交通建设(最小生成树)

时间:2014-03-29 22:17:13      阅读:637      评论:0      收藏:0      [点我收藏+]

题目链接:Problem 1963 交通建设


思路:多建一个虚拟的点,如果有机场,就和这个点相连,然后就是最小生成树问题了,最后要注意如果一开始没有机场,并且最后只有一条边和虚拟点相连,是需要扣掉权值CA的。

代码:

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;

const int N = 1005;
const int M = 12005;
__int64 n, m, ca, cb, p, q, ans, pi, qi, parent[N], i, vis[N], flag;
struct Edge {
	__int64 u, v, value;
	void scan() {
		scanf("%I64d%I64d%I64d", &u, &v, &value);
		value *= cb;
	}
	Edge() {}
	Edge(__int64 _u, __int64 _v, __int64 _value) {
		u = _u; v = _v; value = _value;
	}
} e[M];

__int64 find(__int64 x) {
	if (x == parent[x])
		return x;
	else return parent[x] = find(parent[x]);
}

bool Union(__int64 u, __int64 v) {
	int pa = find(u);
	int pb = find(v);
	if (pa != pb) {
		vis[u]++;
		vis[v]++;
		parent[pa] = pb;
		return true;
	}
	return false;
}

bool cmp(Edge a, Edge b) {
	return a.value < b.value;
}

__int64 solve() {
	sort(e, e + m + n + 1, cmp);
	for (i = 1; i <= m + n; i++) {
		if (Union(e[i].u, e[i].v))
			ans += e[i].value;
	}
	if (vis[n + 1] == 1 && !flag)
		ans -= ca;
	return ans;
}

int main() {
	while (~scanf("%I64d%I64d%I64d%I64d", &n, &m, &ca, &cb)) {
		memset(vis, 0, sizeof(vis));
		ans = 0; flag = 0;
		for (i = 1; i <= n + 1; i++)
			parent[i] = i;
		for (i = 1; i <= m; i++)
			e[i].scan();
		for (i = m + 1; i <= m + n; i++)
			e[i] = Edge(i - m, n + 1, ca);
		scanf("%I64d", &p);
		ans += p * ca;
		while (p--) {
			flag = 1;
			scanf("%I64d", &pi);
			Union(pi, n + 1);
		}
		scanf("%I64d", &q);
		while (q--) {
			scanf("%I64d", &qi);
			ans += e[qi].value;
			Union(e[qi].u, e[qi].v);
		}
		printf("%I64d\n", solve());
	}
	return 0;
}


fzu 1963 交通建设(最小生成树),布布扣,bubuko.com

fzu 1963 交通建设(最小生成树)

原文:http://blog.csdn.net/accelerator_/article/details/22514923

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!