对于一个点,它被它的k级父亲覆盖肯定是最优的。
f[i][j] :i这个点的子树中和它距离为j的待灭点数。
g[i][j]:i这个点的子树中和它距离为j的灭火器能灭点数。
f[i][k]:一定是在i这里灭是最优的,因为相距k.
对于与i相距z的的灭火器(所在点)d2和与i相距w的待灭点d1,如果z + w = k或z + w = k-1(如果再往上走d1,d2就相距k+1就灭不到了)。如果灭火器还能灭,就灭。//每次找距离为k,k-1的,贪心思想,其实i是d1和d2的lca)
对于根来说我们能灭就灭。也就是d1 + d2 < = k 就灭。//距离根小与k的没有k级父亲啊,不能被他的k级父亲灭啊,贪心不了。
再统计有多少灭不了的,加灭火器。
#include<bits/stdc++.h>
using namespace std;
int tp, tov[200005], nex[200005], h[100005], n, s, k, f[100005][22], g[100005][22], ans;
void read(int &x)
{
int f = 0; char c = getchar(); x = 0;
while(c < '0' || c > '9')
{
if(c == '-') f = 1; c = getchar();
}
while(c >= '0' && c <= '9')
{
x = x * 10 + c - '0'; c = getchar();
}
if(f) x = -x;
}
void add(int x,int y)
{
tp++; tov[tp] = y; nex[tp] = h[x]; h[x] = tp;
}
int get(int x)
{
if(x == 0) return 0;
return (x-1) / s + 1;
}
void dfs(int x,int fa)
{
for(int i = h[x]; i; i = nex[i])
{
int v = tov[i]; if(v == fa) continue;
dfs(v,x);
for(int j = 1; j <= k; j++)
{
f[x][j] = f[x][j] +f[v][j-1]; g[x][j] = min(g[x][j]+g[v][j-1],n);
}
}
f[x][0]++;
if(f[x][k])
{
int ha = get(f[x][k]);
g[x][0] =min(n, ha * s);
ans += ha;
}
for(int i = 0; i <= k; i++)
{
int j = k - i;
int ha = min(f[x][i],g[x][j]);
f[x][i] -= ha; g[x][j] -= ha;
}
for(int i = 0; i <= k -1; i++)
{
int j = k - 1 - i;
int ha = min(f[x][i],g[x][j]);
f[x][i] -= ha; g[x][j] -= ha;
}
}
int main()
{
freopen("repulsed.in","r",stdin);
freopen("repulsed.out","w",stdout);
read(n); read(s); read(k);
for(int i = 1; i < n; i++)
{
int x,y;read(x); read(y); add(x,y); add(y,x);
}
dfs(1,1);
for(int i = 0; i <= k; i++)
for(int j = 0; j <= k ;j ++)
{
if(i + j <= k)
{
int ha = min(f[1][i],g[1][j]);
f[1][i] -= ha; g[1][j] -= ha;
}
}
int tmp = 0;
for(int i = 0 ; i<= k; i++)
tmp += f[1][i];
ans += get(tmp);
cout << ans;
return 0;
}