版权声明:未经本蒟蒻同意,请勿转载本蒻博客 https://blog.csdn.net/wddwjlss/article/details/82054665
给定一棵边权为1的树,控制一个点可以控制该节点和与该节点距离小于等于m的点,求最少控制多少个点可以控制一整棵树。
先以1号节点为根进行dfs,并求出每个点的深度。将这些点的深度和这些点的编号放入堆中,每次取出深度最大的节点,如果该节点已经被标记,则弹出该节点。否则对该节点的第m级祖先进行dfs(若该节点没有第m级祖先则对根节点1号节点进行dfs),将该节点第m级祖先和与该节点第m级祖先相距小于等于m的点标记,答案加一。
#include<bits/stdc++.h>
using namespace std;
int n,head[1001000],num,dep[1001000],f[1001000],ans,m,gg,x,fat;
bool book[1001000];
struct node
{
int next,to;
}e[1001000];
priority_queue <pair<int,int> > q;
inline void add(int from,int to)
{
e[++num].next=head[from];
e[num].to=to;
head[from]=num;
}
void dfs(int x,int fa)
{
dep[x]=dep[fa]+1;
f[x]=fa;
for(register int i=head[x];i;i=e[i].next)
{
int v=e[i].to;
if(v==fa)
continue;
dfs(v,x);
}
}
void dfs1(int x,int fa,int deep)
{
if(deep>m)
return;
book[x]=1;
for(register int i=head[x];i;i=e[i].next)
{
int v=e[i].to;
if(v==fa)
continue;
dfs1(v,x,deep+1);
}
}
inline int read()
{
char c=getchar();
while(!isdigit(c))
c=getchar();
int x=c-48;
for(c=getchar();isdigit(c);c=getchar())
x=(x<<3)+(x<<1)+c-48;
return x;
}
int main()
{
n=read();
m=read();
gg=read();
for(int i=1;i<=n-1;++i)
{
int u,v;
u=read();
v=read();
add(u,v);
add(v,u);
}
dfs(1,0);
for(register int i=1;i<=n;++i)
q.push(make_pair(dep[i],i));
while(!q.empty())
{
while(book[x=q.top().second]==1&&!q.empty())
q.pop();
if(q.empty())
break;
fat=x;
for(register int i=1;i<=m;++i)
fat=f[fat];
if(fat)
dfs1(fat,fat,0);
else
dfs1(1,0,0);
++ans;
}
cout<<ans;
return 0;
}