zoukankan      html  css  js  c++  java
  • 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
    ",ans+1);
    31     return 0;
    32 }

     

     

     

  • 相关阅读:
    一个支持asp.net2.0和Sql server及Access的免费空间
    ASP.NET2.0数据指南中文版索引
    所阅读的ASP.NET 2.0文章
    SQL SERVER实用技巧
    2000/XP/2003常见问题集锦
    解讀多重啟動引導文件——BOOT.INI
    【译】Html5游戏开发示例(2)
    unity3d 鼠标事件穿透GUI的处理
    【译】Html5游戏开发示例(3)
    unity3d 截屏
  • 原文地址:https://www.cnblogs.com/al76/p/9696542.html
Copyright © 2011-2022 走看看