JZOJ 5353. 【NOIP2017提高A组模拟9.9】村通网

题目

为了加快社会主义现代化,建设新农村,农夫约(Farmer Jo)决定给农庄里每座建筑都连上互联网,方便未来随时随地网购农药。
他的农庄很大,有N 座建筑,但地理位置偏僻,网络信号很差。
一座建筑有网,当且仅当满足以下至少一个条件:

1、给中国移动交宽带费,直接连网,花费为A。
2、向另外一座有网的建筑,安装共享网线,花费为B×两者曼哈顿距离。

现在,农夫约已经统计出了所有建筑的坐标。他想知道最少要多少费用才能达到目的。

分析

最小生成树
因为我们不确定根,所以可以考虑让 \(0\) 连向每个点,边权 \(A\)

\(Code\)

#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;

const int N = 1005;
int n , A , B , X[N] , Y[N] , dis[N] , vis[N] , e[N][N];

void Prim()
{
	for(register int i = 0; i <= n + 1; i++) dis[i] = 1e9 , vis[i] = 0;
	int k , ans = 0;
	dis[0] = 0;
	for(register int i = 1; i <= n + 1; i++)
	{
		k = n + 1;
		for(register int j = 0; j <= n; j++)
			if (!vis[j] && dis[j] < dis[k]) k = j;
		vis[k] = 1 , ans += dis[k];
		for(register int j = 0; j <= n; j++)
			if (!vis[j] && dis[j] > e[k][j]) dis[j] = e[k][j];
	}
	printf("%d\n" , ans);
}

int main()
{
	freopen("pupil.in" , "r" , stdin);
	freopen("pupil.out" , "w" , stdout);
	scanf("%d%d%d" , &n , &A , &B);
	for(register int i = 1; i <= n; i++) scanf("%d%d" , &X[i] , &Y[i]);
	memset(e , 0x3f3f3f3f , sizeof e);
	for(register int i = 1; i <= n; i++)
		for(register int j = i + 1; j <= n; j++)
			e[i][j] = e[j][i] = (abs(X[i] - X[j]) + abs(Y[i] - Y[j])) * B;
	for(register int i = 1; i <= n; i++) e[0][i] = e[i][0] = A;
	Prim();
}
posted @ 2020-10-17 14:10  leiyuanze  阅读(86)  评论(0编辑  收藏  举报