Linova and Kingdom CodeForces

题目大意:一棵树,然后选k个点,让每个点到根节点的距离之和最大。

题解:求每个点对答案的贡献,假设第i个点的深度为dep,它所具有的子树的大小为tmp,那么他对答案的贡献为dep-tmp,为什么是这样呢?当我们选了一个点c的时候,那么他的子节点一定都被选过了,因为如果没有选过的话,我们完全可以选择它的子节点,这样会更有一点,所以dfs求每个点的深度个每个点的子树节点的数目,然后排序一下就好了。

code:

  

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N=2e5+7;
ll dis[N];//每个点所具有的子节点个数
ll dp[N];//每个点的深度 
bool mark[N];
ll arr[N];
vector<ll>ve[N];
ll dfs(ll x,ll cnt){
    mark[x]=1;
    ll tmp=1;
    for(ll i=0;i<ve[x].size();i++){
        if(!mark[ve[x][i]]) {
            tmp+=dfs(ve[x][i],cnt+1);
        }
    }
    dp[x]=cnt;
    return dis[x]=tmp;
}
bool cmp(const ll x,const ll y){
    return x>y;
}
int main(){
    ll n,k;
    cin>>n>>k;
    ll x,y;
    for(ll i=1;i<n;i++){
        cin>>x>>y;
        ve[x].push_back(y);
        ve[y].push_back(x);
    }
    dfs(1,1);
    for(ll i=1;i<=n;i++){
        arr[i]=dp[i]-dis[i];
    }
    sort(arr+1,arr+1+n,cmp);
    ll ans=0;
    for(ll i=1;i<=k;i++){
        ans+=arr[i];
    }
    cout<<ans<<endl;  
    return 0;
} 
原文地址:https://www.cnblogs.com/Accepting/p/12834704.html