Description
给出N个点的一棵树,边的长度为1
你可以选择在某些上放一个家丁,一个家丁可以控制与此处距离不超过K的所有点。
求最小放置家丁数
Solution
如果是一条链的话,我们很容易想到从底向上贪心,每次当最深的点到当前点为K了就放一个
就是使放的点尽量向上
回到原来的问题
同样的,设
表示当前以i为根的子树中,最近的家丁的距离
如果F[i]为负,则是最远的还没有被控制的点的距离
DFS回溯的时候讨论转移一下即可
Code
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <cmath>
#include <algorithm>
#include <cstring>
#define fo(i,a,b) for(int i=a;i<=b;++i)
#define fod(i,a,b) for(int i=a;i>=b;--i)
#define N 100005
using namespace std;
int f[N],fs[N],nt[2*N],dt[2*N],n,m,l,ans;
void link(int x,int y)
{
nt[++m]=fs[x];
dt[fs[x]=m]=y;
}
void dfs(int k,int fa)
{
int mi=-1,mx=-1;
for(int i=fs[k];i;i=nt[i])
{
int p=dt[i];
if(p!=fa)
{
dfs(p,k);
mi=min(mi,f[p]-1);
mx=max(mx,f[p]-1);
}
}
if(mx>=abs(mi)-1&&mx>=0) f[k]=mx;
else
{
if(mi+1==-l) f[k]=l,ans++;
else f[k]=mi;
}
}
int main()
{
cin>>n>>l;
fo(i,1,n-1)
{
int x,y;
scanf("%d%d",&x,&y);
x++,y++;
link(x,y),link(y,x);
}
if(l==0) printf("%d\n",n);
else
{
dfs(1,0);
if(f[1]<0) ans++;
printf("%d\n",ans);
}
}