题目
为了加快社会主义现代化,建设新农村,农夫约(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
" , 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();
}