题目大意:有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 ",ans); return 0; }