Tutaq ki, dp[v][x] — köklü alt ağacda vərəsələr arasından -dan uzaqlıqda yerləşən zirvələrin sayıdır. dp[v][0] = 1 qəbul edək, çünki zirvəsindən 0 uzaqlıqda yalnız özü yerləşir.
Tutaq ki, zirvəsinin övladları u_1, u_2, ..., u_p var. Onda köklü alt ağacda zirvəsindən uzaqlıqda yerləşən zirvələrin sayı, hər bir u_1, u_2, ..., u_p zirvəsindən x-1 uzaqlıqda yerləşən zirvələrin sayı cəminə bərabərdir.
Tutaq ki, kökü zirvəsi olan alt ağacı nəzərdən keçiririk. Bu alt ağacda tamamilə yerləşən və zirvəsindən keçən uzunluğu olan yolların sayını hesablayaq. Bu cür yolları iki qrupa bölək:
zirvəsində başlayan yollar. Onların sayı dp[v][k]-ə bərabərdir.
zirvəsindən keçən və toplarından biri zirvəsinin oğlunun alt ağaclarında olan yollar.
Köklü alt ağacdan keçən uzunluğu olan bir yol nəzərdən keçirək. Yolun bir ucundan zirvəsinə qədər olan məsafə x~(1 \le x \le k - 1) olsun. Tutaq ki, həmin ucu u_1 zirvəsinin alt ağacında yerləşir. Onda yolun ikinci ucundan zirvəsinə qədər olan məsafə k - x-ə bərabərdir və bu ikinci ucu u_1 zirvəsinin kökü olan alt ağacdan başqa istənilən alt ağacda yerləşə bilər.
Əgər yolun ilk ucundan zirvəsinə qədər olan məsafə -ə bərabərdirsə, onda həmin ucdan u_1 zirvəsinə qədər olan məsafə x - 1-ə bərabərdir. Belə bir ilk uc seçməyin sayı dp[u_1][x - 1]-ə bərabərdir.
İkinci ucu seçməyin sayı zirvəsindən k - x uzaqlıqda yerləşən, lakin u_1 köklü alt ağaca aid olmayan zirvələrin sayına bərabərdir. Bu isə aşağıdakına bərabərdir:
Vurulanın qaydalarına əsasən, bu cür yolların ümumi sayı
Beləliklə, bu cür yolların ümumi sayı
Yuxarıdakı ifadəni ağacın bütün zirvələri üçün toplamaq lazımdır.
Məsələnin nümunəsi
Misala verilmiş ağacın quruluşuna nəzər salaq.
Alqoritmin realizasiyası
Massiv ağacı qıraq siyahıları ilə təqdim edir. Massiv dinamik proqramlaşdırmanın tətbiqi üçün istifadə olunur.
vector<vector<int> > g;
vector<vector<int> > dp;dfs funksiyası zirvəsindən başlayaraq dərinlik birinci axtarışı yerinə yetirir. Burada zirvəsinin qohumunu göstərir. Axtarış zamanı massivini hazırlayırıq.
void dfs(int v, int p = -1)
{Massiv -i indeksləyirik.
dp[v].resize(k+1);
dp[v][0] = 1;Bütün zirvələri keçirik ki, zirvəsindən ona keçid mövcud olsun.
for (int to : g[v])
{
if (to == p) continue;
dfs(to,v);
for(int x = 1; x <= k; x++)
dp[v][x] += dp[to][x-1];
}
}dfsRes funksiyası zirvəsindən başlayaraq dərinlik birinci axtarışı yerinə yetirir və məcruci cavabı hesablamaq üçün nəzərdə tutulur.
void dfsRes(int v, int p = -1)
{
for (int to : g[v])
{
if (to == p) continue;
dfsRes(to,v);
for(int x = 1; x < k; x++)
resA += 1LL * dp[to][x-1] * (dp[v][k-x] - dp[to][k-x-1]);
}
resB += dp[v][k];
}Proqramın əsas hissəsi. Giriş məlumatlarını oxuyuruq. Ağacı qururuq.
scanf("%d %d",&n,&k);
g.resize(n+1);
for (i = 0; i < n - 1; i++)
{
scanf("%d %d",&a,&b);
g[a].push_back(b);
g[b].push_back(a);
}Birinci dərinlik axtarışı ilə massivini qururuq.
dp.resize(n+1);
dfs(1);Axtarılan cavabı hesablamaq və çıxış etmək.
resA = resB = 0;
dfsRes(1);
res = resA / 2 + resB;
printf("%lld\n",res);Python icrası
dfs funksiyası zirvəsindən başlayaraq dərinlik birinci axtarışı yerinə yetirir. Burada zirvəsinin qohumunu göstərir. Axtarış zamanı massivini hazırlayırıq.
def dfs(v, p):Massiv -i indeksləyirik.
dp[v] = [0] * (k + 1)
dp[v][0] = 1Bütün zirvələri keçirik ki, zirvəsindən ona keçid mövcud olsun.
for to in g[v]:
if to == p: continue
dfs(to, v)
for x in range(1, k + 1):
dp[v][x] += dp[to][x - 1]dfsRes funksiyası zirvəsindən başlayaraq dərinlik birinci axtarışı yerinə yetirir və məcruci cavabı hesablamaq üçün nəzərdə tutulur.
def dfsRes(v, p):
global resA, resB
for to in g[v]:
if to == p: continue
dfsRes(to, v)
for x in range(1, k):
resA += dp[to][x - 1] * (dp[v][k - x] - dp[to][k - x - 1])
resB += dp[v][k]Proqramın əsas hissəsi. Ağacın zirvələri və arasındakı məsafəni oxuyuruq.
n, k = map(int, input().split())siyahısında ağacın qraf siyahıları ilə təqdimatı saxlanılır. siyahısı dinamik proqramlaşdırmanın tətbiqi üçün istifadə olunur.
g = [[] for _ in range(n + 1)]
dp = [[] for _ in range(n + 1)]Kənarların siyahısını oxuyuruq. Ağacı qururuq.
for _ in range(n - 1):
a, b = map(int, input().split())
g[a].append(b)
g[b].append(a)Birinci dərinlik axtarışı ilə massivini qururuq.
dfs(1, -1)Axtarılan cavabı hesablamaq və çıxış etmək.
resA, resB = 0, 0
dfsRes(1, -1)
res = resA // 2 + resB
print(res)