CF1042F Leaf Sets(题解)

F. Leaf Sets

给定一棵n个点的树,将叶子节点分为数个集合使集合里点对最长距离不超过k,求最少集合数。

 

 

You are given an undirected tree, consisting of n vertices.

The vertex is called a leaf if it has exactly one vertex adjacent to it.

The distance between some pair of vertices is the number of edges in the shortest path between them.

Let's call some set of leaves beautiful if the maximum distance between any pair of leaves in it is less or equal to kk.

You want to split all leaves into non-intersecting beautiful sets. What is the minimal number of sets in such a split?

Input

The first line contains two integers nn and kk (3n1e6,1≤k≤1e6) — the number of vertices in the tree and the maximum distance between any pair of leaves in each beautiful set.

Each of the next n1n−1 lines contains two integers vivi and uiui (1vi,uin1≤vi,ui≤n) — the description of the ii-th edge.

It is guaranteed that the given edges form a tree.

Output

Print a single integer — the minimal number of beautiful sets the split can have.

Examples
input
9 3
1 2
1 3
2 4
2 5
3 6
6 7
6 8
3 9
output
2
input
5 3
1 2
2 3
3 4
4 5
output
2
input
6 1
1 2
1 3
1 4
1 5
1 6
output
5
Note

Here is the graph for the first example:

题解:这道题的题意比较清晰,就不多解释啦。

对于关于树的问题,有一个很常见的方法:找到一个非叶子节点作为根,然后一边dfs一边处理子树中的问题,一路合并上去。

若a,b为节点x的儿子,我们假设d_a为以a为根的子树中与a最远的叶子与a的距离(也就是以a为根的子树的深度),d_b同理。

在判断a、b能否合并时,我们只需要判断da+db+2<=k是否成立即可。假如我们知道x所有儿子的d值,就可以贪心地合并啦-v-

设x儿子d值的集合(允许重复)为A,如果A中任意两个元素的和都<=k那么答案不会增加,因为没有无法融合的集合。

但是如果有>k的怎么办?为了解决这个问题,我们需要对A排序,设A中最大元素为d_max1,第二大元素为d_max2,d_max2<=d_max1,

如果d_max1+d_max2+2>k,说明这两个元素对应子树中的叶子不能放在一个集合里,于是把d_max1从A中删除,ans++。

为了方便地求出A集合,在dfs时返回删完之后A集合中的最大值就行。

时间复杂度O(nlogn):对每个节点的所有儿子一遍排序,1e6可能会卡,但是这道题开了3s,欸嘿嘿~

 

这里是代码↓

 

 1 #include <cstdio>
 2 #include <vector>
 3 #include <algorithm>
 4 #define maxn 1000010
 5 using namespace std;
 6 bool vis[maxn];
 7 int n,k,u,v,ans;
 8 vector<int> ve[maxn];
 9 void add(int x,int y){ve[x].push_back(y);}
10 int dfs(int x){
11     vis[x]=1;
12     if(ve[x].size()==1) return 0;
13     vector<int> tmp;
14     for(int i=0;i<ve[x].size();i++){
15         int v=ve[x][i];
16         if(!vis[v]) tmp.push_back(dfs(v)+1);
17     }
18     sort(tmp.begin(),tmp.end());
19     while(tmp.size()>1){
20         int sz=tmp.size();
21         if(tmp[sz-1]+tmp[sz-2]<=k) break;
22         ans++,tmp.pop_back();
23     }
24     return tmp.back();
25 }
26 int main(){
27     scanf("%d%d",&n,&k);
28     for(int i=1;i<n;i++)scanf("%d%d",&u,&v),add(u,v),add(v,u);
29     for(int i=1;i<=n;i++)if(ve[i].size()>1){dfs(i);break;}
30     printf("%d\n",ans+1);
31     return 0;
32 }

 

 

 

posted @ 2018-09-24 20:22  AL76  阅读(326)  评论(0编辑  收藏  举报