F. Leaf Sets(搜索 叶子分集合)

http://codeforces.com/problemset/problem/1042/F

题意:

给出一棵树,将所有叶子节点分成若干个集合,每个集合的任意两个叶子之间的距离不超过K,求集合的个数最小值。

解析:

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

证明:

在这里插入图片描述

复杂度的话,自己不管怎么造数据,都顶多 O ( N ) O(N) ,所以直接上了。

代码:

#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define pill pair<int,int>
#define LL long long
 
int n,k;
const int maxn=1e6+9;
int head[maxn],nex[maxn<<1],to[maxn<<1],now;
void add(int a,int b){
    nex[++now]=head[a];head[a]=now;to[now]=b;
}
int deg[maxn];
int dep[maxn];
priority_queue<pill>Q;
 
void dfs(int p,int fa,int d){
    dep[p]=d;
    int son=0;
    for(int i=head[p];i;i=nex[i]){
        int u=to[i];
        if(u==fa)continue;
        dfs(u,p,d+1);
        son++;
    }
    if(son==0)Q.push({d,p});
}
 
bool vis[maxn];
void dfs2(int p,int fa,int len){
    vis[p]=1;
    if(len==k)return;
    for(int i=head[p];i;i=nex[i]){
        int u=to[i];
        if(u==fa)continue;
        dfs2(u,p,len+1);
    }
}
 
int main(){
    scanf("%d%d",&n,&k);
    rep(i,1,n-1){
        int a,b;scanf("%d%d",&a,&b);
        add(a,b),add(b,a);
        deg[a]++;deg[b]++;
    }
    if(n==2){
        return 0*printf("1\n");
    }
    int rt;
    rep(i,1,n)if(deg[i]>1)rt=i;
    dfs(rt,-1,1);
    int ans=0;
    while(!Q.empty()){
        pill P=Q.top();Q.pop();
        if(vis[P.second])continue;
        ans++;
        dfs2(P.second,-1,0);
    }
    printf("%d\n",ans);
}
发布了723 篇原创文章 · 获赞 314 · 访问量 16万+

猜你喜欢

转载自blog.csdn.net/jk_chen_acmer/article/details/103190967
今日推荐