1042F.Leaf Sets(贪心)

题意:

给出一棵树。

定义一个叶子集合为:

集合中任意一对叶子之间的距离小于等于k

询问最少可以把叶子分成几个集合。

做法:

考虑每次从最深的点开始搜索,这样可以保证,搜K次搜到的点之间的距离不超过K。

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+100;
int n,k,rt;
int dep[maxn];
vector<int> g[maxn];
int vis[maxn];
int p[maxn];
int cmp (int x,int y) {
    return dep[x]>dep[y];
}
void dfs1 (int x,int f) {
    dep[x]=dep[f]+1;
    for (int y:g[x]) if (y!=f) dfs1(y,x);
}
void dfs2 (int x,int f,int d) {
    vis[x]=1;
    //printf("%d ",x);
    if (d==k) return;
    for (int y:g[x]) if (y!=f) dfs2(y,x,d+1);
} 
int main () {
    scanf("%d%d",&n,&k);
    for (int i=1;i<=n;i++) p[i]=i;
    for (int i=1;i<n;i++) {
        int x,y;
        scanf("%d%d",&x,&y);
        g[x].push_back(y);
        g[y].push_back(x);
        if (!rt&&g[x].size()>1) rt=x;
        if (!rt&&g[y].size()>1) rt=y;
    }
    dfs1(rt,0);
    sort(p+1,p+n+1,cmp);
    //for (int i=1;i<=n;i++) printf("%d ",p[i]);
    //printf("
");
    int ans=0;
    for (int i=1;i<=n;i++) {
        if (vis[p[i]]) continue;
        if (g[p[i]].size()>1) continue;
        ans++;
        dfs2(p[i],0,0);
        //printf("
");
    }
    printf("%d
",ans);
}

这是一个重要的结论,可能会碰到相似的模型。

原文地址:https://www.cnblogs.com/zhanglichen/p/14393778.html