C. Linova and Kingdom

n个点的树型结构,选择k个工业城市,其他都是旅游城市,问所有工业城市到1节点的幸福值总和最大多少。幸福值为经过的旅游城市的个数。
优先的想法肯定是深度越大越好。
但是考虑一下,对于一棵树的内部节点而言,一定要经过根u,如果根被选为工业城市,那么增加的幸福值就是dep[u]-siz[u]
什么意思呢?就是如果选了这个节点为工业城市,那么子树内部的工业城市的幸福值都要减少1,
之所以减去的是树的大小,是因为基于深度越大越好,所以肯定是优先把树内部的点选上,而增加的就是u到节点1的路径长度也就是深度。
首先以dep[x]-siz[x]从大到小排序取前k大的和即可。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
vector<int> e[1 << 21];
int siz[1 << 21], dep[1 << 21];
int cnt[1 << 21];
void dfs(int x, int f)
{
    dep[x] = dep[f] + 1;
    siz[x] = 1;
    for (auto it : e[x])
    {
        if (it == f)
            continue;
        dfs(it, x);
        siz[x] += siz[it];
    }
}
int main()
{
    int n, k;
    cin >> n >> k;
    for (int i = 1; i < n; i++)
    {
        int x, y;
        cin >> x >> y;
        e[x].push_back(y);
        e[y].push_back(x);
    }
    dfs(1, -1);
    for (int i = 1; i <= n; i++)
        cnt[i] = i;
    sort(cnt + 1, cnt + 1 + n, [](int x, int y) {
        return dep[x] - siz[x] > dep[y] - siz[y];
    });
    ll ans = 0;
    for (int i = 1; i <= k; i++)
    {
        ans += dep[cnt[i]] - siz[cnt[i]];
    }
    cout << ans << endl;

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我不会c语言

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值