【最小生成树】JZOJ_5353 村通网

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/SSL_hzb/article/details/85393851

题意

N N 个村,它们需要联网,联网的方式有两种:
1、直接联网,花费 A A
2、与另一个村连起来,花费 B B* 它们之间的曼哈顿距离,如果另一个村有网,那么这个村也会有网。
求最小花费。

思路

直接做最小生成树,特别要注意的是,如果两村连起来的花费超过 A A 元我们就不连,因为直接联网会比这样更优,最后给每个联通块加上 A A ,表示每个块都有一个村有网共享给它们。

代码

#include<cmath>
#include<cstdio>
#include<algorithm>

struct node{
	int x, y, v;
}e[1000001];

int x[1001], y[1001], fa[1001];
int ans;

int find(int x) {
	return x == fa[x] ? x : fa[x] = find(fa[x]);
}

int cmp(node x, node y) {
	return x.v < y.v;
}

int main() {
	int n, a, b, cnt = 0;
	scanf("%d %d %d", &n, &a, &b);
	for (int i = 1; i <= n; i++)
		scanf("%d %d", &x[i], &y[i]);
	for (int i = 1; i < n; i++)
		for (int j = i + 1; j <= n; j++)
			e[++cnt] = (node){i, j, abs(x[i] - x[j]) + abs(y[i] - y[j])};
	for (int i = 1; i <= n; i++)
		fa[i] = i;
	std::sort(e + 1, e + cnt + 1, cmp);
	for (int i = 1; i <= n; i++) {
		int f1 = find(e[i].x), f2 = find(e[i].y);
		if (f1 == f2) continue;
		if (e[i].v * b <= a) {
			fa[f1] = f2;
			ans += e[i].v * b;
		}
	}
	for (int i = 1; i <= n; i++)
		if (fa[i] == i) ans += a;
	printf("%d", ans);
}

猜你喜欢

转载自blog.csdn.net/SSL_hzb/article/details/85393851
今日推荐