div2贪心+建树

C. Linova and Kingdom

Writing light novels is the most important thing in Linova’s life. Last night, Linova dreamed about a fantastic kingdom. She began to write a light novel for the kingdom as soon as she woke up, and of course, she is the queen of it.

There are n cities and n−1 two-way roads connecting pairs of cities in the kingdom. From any city, you can reach any other city by walking through some roads. The cities are numbered from 1 to n, and the city 1 is the capital of the kingdom. So, the kingdom has a tree structure.

As the queen, Linova plans to choose exactly k cities developing industry, while the other cities will develop tourism. The capital also can be either industrial or tourism city.

A meeting is held in the capital once a year. To attend the meeting, each industry city sends an envoy. All envoys will follow the shortest path from the departure city to the capital (which is unique).

Traveling in tourism cities is pleasant. For each envoy, his happiness is equal to the number of tourism cities on his path.

In order to be a queen loved by people, Linova wants to choose k cities which can maximize the sum of happinesses of all envoys. Can you calculate the maximum sum for her?

Input
The first line contains two integers n and k (2≤n≤2⋅105, 1≤k<n) — the number of cities and industry cities respectively.

Each of the next n−1 lines contains two integers u and v (1≤u,v≤n), denoting there is a road connecting city u and city v.

It is guaranteed that from any city, you can reach any other city by the roads.

Output
Print the only line containing a single integer — the maximum possible sum of happinesses of all envoys.

#include<bits/stdc++.h>
#define ll long long

using namespace std;

vector<int>G[200001];
ll len[200001];   //高度
int fa[200001];  //父亲节点
ll son[200001]; //子儿子数目
struct lll{
ll so;
ll dep;
int inde;

}ans[200001];
bool cmp(lll &node1,lll &node2){

return node1.so-node1.dep+1<node2.so-node2.dep+1;  //因为减的是高度所以再+1
}
void dfs(int u,int f,ll step){
fa[u]=f;
len[u]=step;
int n=G[u].size();
for (int i=0;i<n;i++){
int v=G[u][i];
if(v==f) continue;
dfs(v,u,step+1);
son[u]+=son[v];
}

}
int main()
{
int n,k;
cin>>n>>k;
len[0]=0;
for (int i=0;i<n-1;i++){
int a,b;
cin>>a>>b;
G[a].push_back(b);
G[b].push_back(a);
}
son[1]=G[1].size();
for (int i=2;i<=n;i++){
son[i]=G[i].size()-1; //子儿子数等于本身儿子 在进行dfs加上孙子
}
dfs(1,0,1);
for (int i=2;i<=n;i++){
ans[i].so=son[i];
ans[i].dep=len[i];
ans[i].inde=i;
}
ll sum=n-1;
sort(ans+2,ans+n+1,cmp);
int i=n;
k=n-k-1;
while(k){

sum+=ans[i].so-len[fa[ans[i].inde]];   //加上每个旅游区的贡献
k--;
i--;
}
cout<<sum;
}


• 0
点赞
• 0
收藏
觉得还不错? 一键收藏
• 0
评论
04-16 270
04-28 334
04-16 578
12-29
04-24
07-23
04-16

“相关推荐”对你有帮助么？

• 非常没帮助
• 没帮助
• 一般
• 有帮助
• 非常有帮助

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