【Codeforces Round #635 (Div. 2) C】Linova and Kingdom

题目链接

点我呀

翻译

给你一棵树, 让你在这棵树上选择恰好k个点, 这k个点是发展工业的, 然后其余的n - k个点发展旅游业。

但是根节点(约定1号节点是根节点)例外, 它可以发展旅游业也可以发展工业(不过后面会发现这条件没啥用。。)。

假设x是你选出来的k个点中的一个, 对于所有的x, 你需要求出每个节点x到根节点1会经过的 发展旅游业 的节点个数\(cnt_i\), 然后对cnt求和,

求和的结果设为sum, 你需要找到这样的k个节点的安排, 使得sum的值最大。

题解

所以, 为啥根节点可以发展旅游业或者工业这个信息没用呢? 因为你会发现不管什么情况下, 让根节点发展旅游业总是更好的。

这样工业节点能多算一次旅游节点嘛。

然后就是自己画画图模拟一下了, 会发现, 你肯定是想选出来的工业结点越靠近最底层越好(实际上是, 离根节点越远越好)。

以下图为例

你肯会先选离根节点最远的, 也就是用蓝笔标记的①号节点, 然后是②号, 这两个点会经过的旅游节点的个数就是它们的树的高度。

但是有个问题, 最先选出来的两个节点很好办, 它们也没有分支什么的, 经过的旅游节点个数很好算,

但是如果选③号节点的话, 怎么办呢? 选择它的话, 会让它底下所有的节点对答案的贡献都减少1, 这点没错。

那, 会不会下面有哪个节点没有选呢? 肯定不会的! 我们可以由节点从高到低排序, 这样就能保证下面的节点先被选到。

因为底下所有的节点对答案贡献都会减少1, 所以选择了这个节点x对答案的贡献就是height[x] - _size[x] - 1, 这里的

height[x]表示树的高度, _size[x]表示以x为根的子树的大小(包括x)。

所以, 处理出来这个数组, 逆序排序, 然后选最大的k个累加起来就行。

题解中学来的一个性质 :一个旅游节点上面, 不可能存在有一个工业节点, 因为那样的话, 旅游节点和工业节点直接能调换一下, 这样工业节点就能多

累加一个旅游节点的值, 更优了。

所以类似B题, 旅游节点都是在树的路径上连续的一些节点。

代码

#include<bits/stdc++.h>
#define ll long long
#define rei(x) scanf("%d",&x)
#define rel(x) scanf("%I64d",&x)
#define rep1(i,a,b) for (int i = a;i <= b;i++)
#define rep2(i,a,b) for (int i = a;i >= b;i--)
using namespace std;

const int N = 2e5;

int n,k;
vector<int> g[N+10];
int _size[N+10],_height[N+10];
int p[N+10];

void dfs(int x,int fa){
    _size[x] = 1;
    int len = g[x].size();

    rep1(i,0,len-1){
        int y = g[x][i];
        if (y==fa) continue;
        _height[y] = _height[x] + 1;
        dfs(y,x);
        _size[x] += _size[y];
    }

    p[x] = _height[x]-(_size[x]-1);
}

int main(){
    #ifdef LOCAL_DEFINE
        freopen("D:\\rush.txt","r",stdin);
    #endif
    ios::sync_with_stdio(0),cin.tie(0);
    cin >> n >> k;
    rep1(i,1,n-1){
        int x,y;
        cin >> x >> y;
        g[x].push_back(y);
        g[y].push_back(x);
    }
    _height[1] = 0;
    dfs(1,0);
    sort(p+1,p+1+n);
    reverse(p+1,p+1+n);
    ll sum = 0;
    rep1(i,1,k){
        sum = sum + p[i];
    }
    cout<<sum<<endl;
    return 0;
}
posted @ 2020-06-14 15:13  AWCXV  阅读(152)  评论(0编辑  收藏  举报