2017年9月16日提高组T2 A 电脑都连上互联网

Description


为了加快社会主义现代化,建设学校,小明决定给学校里每台电脑都连上互联网,方便未来随时随地玩耍。
他的电脑室很大,有N 台电脑,但地理位置偏僻,网络信号很差。
一台电脑有网,当且仅当满足以下至少一个条件:
1、给中国移动交宽带费,直接连网,花费为A。
2、向另外一台有网的电脑,安装共享网线,花费为B×两者曼哈顿距离。
现在,小明已经统计出了所有电脑的坐标。他想知道最少要多少费用才能达到目的。

Input


第一行:三个正整数,代表N、A、B。
接下来N 行:每行两个整数Xi、Yi,第i 行代表第i 台电脑的坐标。

Output


第一行:一个整数,代表答案

Hint


30%的数据:N <= 3,A <= 50,B <= 5
60%的数据:N <= 100,A <= 1000,B <= 20
100%的数据:N <= 10^3,A <= 10^4,B <= 50,|Xi|,|Yi| < 2^15

Source


YPX

Solution


整理题意,我们需要使用最少的边将n个点连起来且至少一个点连在一个超级点上边权为A。很容易想到是最小生成树。

Code


#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#define rep(i, st, ed) for (int i = st; i <= ed; i += 1)
#define drp(i, st, ed) for (int i = st; i >= ed; i -= 1)
#define erg(i, st) for (int i = ls[st]; i; i = e[i].next)
#define fill(x, t) memset(x, t, sizeof(x))
#define max(x, y) (x)>(y)?(x):(y)
#define min(x, y) (x)<(y)?(x):(y)
#define ll long long
#define N 1024
#define E N * N / 2 + 1
#define L 1021
struct edge {int x, y, w;} e[E];
int fa[N], x[N], y[N], edgeCnt = 0;
inline void addEdge(int x, int y, int w) {
    e[++ edgeCnt] = (edge) {x, y, w};
}
inline int read() {
    int num = 0, v = 1; char ch = getchar();
    for(; ch<'0'||ch>'9'; v=(ch=='-')?(-1):(v), ch=getchar());
    for(; ch<='9'&&ch>='0'; (num*=10)+=ch-'0',ch=getchar());
    return num * v;
}
inline int getFather(int a) {
    return (fa[a] == a)?(a):(fa[a] = getFather(fa[a]));
}
inline int abs(int a) {
    return (a<0)?(-a):(a);
}
inline int dis(int a, int b) {
    return abs(x[a] - x[b]) + abs(y[a] - y[b]);
}
inline bool cmp(edge a, edge b) {
    return a.w < b.w;
}
inline bool merge(int a, int b) {
    int fx = getFather(a);
    int fy = getFather(b);
    if (fx == fy) {return false;}
    fa[fx] = fa[fy];
    return true;
}
int main(void) {
    std:: ios:: sync_with_stdio(false);
    int n = read();
    int A = read();
    int B = read();
    rep(i, 1, n) {
        x[i] = read();
        y[i] = read();
        fa[i] = i;
        addEdge(0, i, A);
    }
    rep(i, 1, n - 1) {
        rep(j, i + 1, n) {
            addEdge(i, j, dis(i, j) * B);
        }
    }
    std:: sort(e + 1, e + edgeCnt + 1, cmp);
    ll ans = 0;
    int cnt = 0;
    rep(i, 1, edgeCnt) {
        if (cnt == n) {
            break;
        }
        if (merge(e[i].x, e[i].y)) {
            ans += e[i].w;
            cnt += 1;
        }
    }
    std:: cout << ans << std:: endl;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值