• Codeforces Round #635C Linova and Kingdom 思维


    Linova and Kingdom

    题意

    现在有一颗n个节点的树,每个节点是一个城市,现在要选出k个城市作为工业城市,其他城市作为旅游城市,现在每个工业城市要派出一名特使前往根节点,每个特使的幸福度为经过的旅游城市的数量,求最大的幸福度总和。

    思路

    对于某个节点u,如果u是工业城市,那么它的子节点肯定是工业城市。

    如果它的某个子节点不是,我们完全可以把它的子节点作为工业城市,而不是u。

    我们再看如果选择了u作为工业城市,幸福度发生的变化。

    假如本来总幸福度是ans

    定义根节点的深度为1,u是不是工业城市只会对它的子树有影响

    ans=ans-(sum[u]-1)*dep[u]先减去u为旅游城市时,子树的幸福度

    ans=ans+sum[u]*(dep[u]-1)加上u变为工业城市时,子树的幸福度

    化简一下:

    ans=ans+dep[u]-sum[u]

    如果u节点作为工业城市,它的贡献为dep[u]-sum[u],即深度-子树大小

    我们按照每个节点的深度-子树大小从大到小排序,取前k个。

    代码

    #include<bits/stdc++.h>
    #define pb push_back
    using namespace std;
    typedef long long ll;
    const int N=1e6+10;
    
    vector<int>xiao[N],vec;
    int dep[N],sum[N];
    void dfs(int u,int pre)
    {
        sum[u]=1;
        for(int v:xiao[u])
        {
            if(v==pre) continue;
            dep[v]=dep[u]+1;
            dfs(v,u);
            sum[u]+=sum[v];
        }
    }
    bool cmp(int a,int b)
    {
        return (dep[a]-sum[a])>(dep[b]-sum[b]);
    }
    int main()
    {
        int n,k;
        scanf("%d%d",&n,&k);
        for(int i=1;i<n;i++)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            xiao[u].pb(v);
            xiao[v].pb(u);
        }
        for(int i=1;i<=n;i++)
            vec.pb(i);
        dep[1]=1;
        dfs(1,1);
        sort(vec.begin(),vec.end(),cmp);
        ll maxn=0;
        for(int i=0;i<k;i++)
        {
            int u=vec[i];
            maxn+=dep[u]-sum[u];
        }
        printf("%lld
    ",maxn);
        return 0;
    }
    
  • 相关阅读:
    Delphi XE5 android 蓝牙通讯传输
    Delphi XE5 android toast
    Delphi XE5 android openurl(转)
    Delphi XE5 如何设计并使用FireMonkeyStyle(转)
    Delphi XE5 android 捕获几个事件
    Delphi XE5 android listview
    Delphi XE5 android 黑屏的临时解决办法
    Delphi XE5 android popumenu
    Delphi XE5 android 获取网络状态
    Delphi XE5 android 获取电池电量
  • 原文地址:https://www.cnblogs.com/valk3/p/12775434.html
Copyright © 2020-2023  润新知