题目大意:一棵树,然后选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; }