Codeforces Round #635 (Div. 2) C - Linova and Kingdom(树形dp+思维)

Linova and Kingdom

time limit per test

2 seconds

memory limit per test

256 megabytes

input

standard input

output

standard output

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.

df63f4ac458c231c1258e895434dcb4c2f090f09.pnguploading.4e448015.gif转存失败重新上传取消df63f4ac458c231c1258e895434dcb4c2f090f09.pnguploading.4e448015.gif正在上传…重新上传取消df63f4ac458c231c1258e895434dcb4c2f090f09.pnguploading.4e448015.gif转存失败重新上传取消

 

There are nn cities and n−1n−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 11 to nn, and the city 11 is the capital of the kingdom. So, the kingdom has a tree structure.

As the queen, Linova plans to choose exactly kk 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 kk 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 nn and kk (2≤n≤2⋅1052≤n≤2⋅105, 1≤k<n1≤k<n)  — the number of cities and industry cities respectively.

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

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.

Examples

input

7 4
1 2
1 3
1 4
3 5
3 6
4 7

output

7

input

4 1
1 2
1 3
2 4

output

2

input

8 5
7 5
1 7
6 1
3 7
8 3
2 1
4 5

output

9

Note

In the first example, Linova can choose cities 22, 55, 66, 77 to develop industry, then the happiness of the envoy from city 22 is 11, the happiness of envoys from cities 55, 66, 77 is 22. The sum of happinesses is 77, and it can be proved to be the maximum one.

In the second example, choosing cities 33, 44 developing industry can reach a sum of 33, but remember that Linova plans to choose exactly kk cities developing industry, then the maximum sum is 22.

题意:

给你一颗n(<=2e5)个节点的无向树,其中1为根,你要选择恰好k个结点染色,使得这k个点到根的路径中每个点经过的未染色点的数量之和最大。

思路:感觉这题比同场的D更难一些。首先就是题意有些迷,刚开始读成了选k个点,使得这k个点到根节点的路径长度之和最大。一想这不就是求深度最大的k个点吗?然后样例第三组就过不去。。。

实际上思路差不多。我们依然从深度最大的点开始选,如果是叶节点,那么就直接选,贡献就是该节点到根节点的距离,否则这个节点的贡献就是 该节点到根节点的距离-该节点为根的子树的大小+1(因为每个孩子节点在父节点被选之前一定全都被选了,一旦选择父节点,所有孩子节点经过的未染色点就会都减少一个)

我一共WA了三发:①读错题意②答案在计算到某一步的时候可能开始减少③每个非叶子节点都会改变且只改变一次自己对答案的贡献

代码:

#include<bits/stdc++.h>
#define ll long long
#define inf 0x3f3f3f3f
#define rep(i,a,b) for(register int i=(a);i<=(b);i++)
#define dep(i,a,b) for(register int i=(a);i>=(b);i--)
using namespace std;
const int maxn=4e5+5;
//const double pi=acos(-1.0);
//const double eps=1e-9;
//const ll mo=1e9+7;
int n,m,k,q;
int fa[maxn],dp[maxn];
int ans,tmp,cnt;
int flag;
int ok[maxn];
vector<int>vc[maxn],a[maxn];
void dfs(int u,int f,int dep){
    a[dep+n].push_back(u);
    dp[u]=1;fa[u]=f;
    for(int i=0;i<vc[u].size();i++){
        int v=vc[u][i];
        if(v==f) continue;
        dfs(v,u,dep+1);
        dp[u]+=dp[v];
    }
}
int main()
{
    int T,cas=1;
    //scanf("%d",&T);
    //while(T--)
    {
        scanf("%d%d",&n,&k);
        rep(i,1,n-1){
            int x,y;
            scanf("%d%d",&x,&y);
            vc[x].push_back(y);
            vc[y].push_back(x);
        }
        dfs(1,0,0);
        ll ans=0;
        dep(i,2*n,0) if(a[i].size()&&k>0){
            for(int j=0;j<a[i].size();j++){
                int v=a[i][j];
                if(k<=0) break;
                if((dp[v]==1)||(ok[v])) {
                    ans+=i-n;k--;
                    //cout<<v<<" "<<ans<<" "<<k<<endl;
                }
                else {
                    //cout<<v<<" "<<i-dp[v]+1<<endl;
                    a[i-dp[v]+1].push_back(v);ok[v]=1;
                }
            }
        }
        printf("%lld\n",ans);
    }
    return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值