http://codeforces.com/problemset/problem/1042/F
题意:
给出一棵树,将所有叶子节点分成若干个集合,每个集合的任意两个叶子之间的距离不超过K,求集合的个数最小值。
解析:
考虑每次从最深的点开始搜索,这样可以保证搜K次搜到的点之间的距离不超过K。
证明:
复杂度的话,自己不管怎么造数据,都顶多 ,所以直接上了。
代码:
#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);
}