题目大意:有n个驿站形成一棵树。一支小队在某个驿站驻扎时,可以控制与这个驿站距离不超过k的所有驿站(每条边长度算1)。问至少需要驻扎多少小队?
解题思路:贪心。要控制所有驿站,我们从最深的节点开始考虑。
要使一支小队控制到这个节点,又要让它贡献尽可能多,我们应该让它驻扎在当前节点的第k个祖先的节点上。
然后把所有已经被控制的节点打上标记。
接着从剩下的、没被打上标记的最深的节点考虑,继续如上方法贪心即可。
打标记的过程dfs一遍即可。
最后驻扎了几支小队,答案就是多少。
注意当一个节点没有第k个祖先(即它的某个祖先是根节点且不为第k个祖先),则直接让其驻扎在根节点上。
C++ Code:
#include<cstdio>
#include<cctype>
#include<cstring>
#include<algorithm>
using namespace std;
int n,k,head[100005],cnt,fa[100005];
bool vis[100005];
struct edge{
int to,nxt;
}e[200010];
struct Deep{
int s,num;
bool operator <(const Deep& rhs)const{return s>rhs.s;}
}dep[100005];
inline int readint(){
char c=getchar();
for(;!isdigit(c);c=getchar());
int d=0;
for(;isdigit(c);c=getchar())
d=(d<<3)+(d<<1)+(c^'0');
return d;
}
void dfs(int now){
for(int i=head[now];i;i=e[i].nxt)
if(e[i].to!=fa[now]){
fa[e[i].to]=now;
dep[e[i].to]=(Deep){dep[now].s+1,e[i].to};
dfs(e[i].to);
}
}
void fg(int now,int p,int pre){
vis[now]=true;
if(k!=p++)
for(int i=head[now];i;i=e[i].nxt)
if(e[i].to!=pre)
fg(e[i].to,p,now);
}
int main(){
cnt=0;
memset(dep,0,sizeof dep);
memset(head,0,sizeof head);
n=readint(),k=readint();readint();
for(int i=1;i<n;++i){
int u=readint(),v=readint();
e[++cnt]=(edge){v,head[u]};
head[u]=cnt;
e[++cnt]=(edge){u,head[v]};
head[v]=cnt;
}
fa[1]=1;
dep[1]=(Deep){1,1};
dfs(1);
sort(dep+1,dep+n+1);
memset(vis,0,sizeof vis);
int ans=0;
for(int i=1;i<=n;++i)
if(!vis[dep[i].num]){
int grf=dep[i].num;
for(int j=1;j<=k;++j)grf=fa[grf];
fg(grf,0,grf);
++ans;
}
printf("%d\n",ans);
return 0;
}