CF1245D: Shichikuji and Power Grid

CF1245D: Shichikuji and Power Grid

题意描述:

  • 给定\(n\)个点\((n\leq2000)\),在第\(i\)个点上建立一个基站需要\(c_i\)的代价,连接两个点需要\((|x_i-x_j|+|y_i-y_j|)*(k_i+k_j)\)的代价。对于一个点要么建立基站,要么连接建立基站的点。问最小代价是多少,同时输出建立基站的点和线路。

思路:

  • 建立一个超级根,对于每个城市建立发电站,连接一条权值为\(c_i\)的边,再把每个城市之间连接电线的花费算出来,跑\(kruskal\)
  • 在跑的过程中记录哪些城市建立了发电站,哪些城市建立了电线。
  • \(hint:\)注意开\(long\ long\)

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const int maxn = 2000 + 10;
int n;
ll ans, x[maxn], y[maxn], k[maxn], c[maxn];
struct Node{
    int x, y;
    ll z;
}p[maxn*maxn];

int tot;
void add_edge(int x, int y, ll z){
    p[++tot].x = x, p[tot].y = y, p[tot].z = z;
}

int fa[maxn];

bool cmp(Node a, Node b){
    return a.z < b.z;
}

int get_fa(int x)
{
    if(x == fa[x]) return x;
    return fa[x] = get_fa(fa[x]);
}

int ans1[maxn], cnt1;
int ax[maxn], ay[maxn], cnt2;

void kruskal()
{
    for(int i = 0; i <= n; i++) fa[i] = i;
    sort(p+1, p+1+tot, cmp);
    int cnt = 0;
    for(int i = 1; i <= tot; i++)
    {
        int x = p[i].x, y = p[i].y;
        ll z = p[i].z;
        int fx = get_fa(x), fy = get_fa(y);
        if(fx != fy)
        {
            if(x == 0 || y == 0) ans1[++cnt1] = x + y;
            else ax[++cnt2] = x, ay[cnt2] = y;
            ans += z; fa[fx] = fy; cnt++;
        }
        if(cnt == n) break;
    }
    cout << ans << endl;
}

int main()
{
    scanf("%d", &n);
    for(int i = 1; i <= n; i++)
        scanf("%lld%lld", &x[i], &y[i]);
    for(int i = 1; i <= n; i++) scanf("%lld", &c[i]);
    for(int i = 1; i <= n; i++) scanf("%lld", &k[i]);

    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= n; j++)
    {
        if(i != j)
        {
            ll w = (k[i] + k[j]) * (abs(x[i]-x[j]) + abs(y[i]-y[j]));
            add_edge(i, j, w);
        }
    }

    for(int i = 1; i <= n; i++)
        add_edge(0, i, c[i]), add_edge(i, 0, c[i]);

    kruskal();
    cout << cnt1 << endl;
    for(int i = 1; i <= cnt1; i++)
        printf("%d ", ans1[i]); puts("");
    cout << cnt2 << endl;
    for(int i = 1; i <= cnt2; i++)
        printf("%d %d\n", ax[i], ay[i]);
    return 0;
}
posted @ 2019-11-02 12:06  zhaoxiaoyun  阅读(332)  评论(0编辑  收藏  举报