Virus ağacı 2#10655

Virus ağacı 2 (Həll təhlili)

Ağacın boyanmasına zirvəsindən başlayırıq. Onu rənglə boyamaq olar.

Tutaq ki, biz zirvəsində yerləşirik. Əgər onun atası yoxdursa (v = 1), onda oğlanları k - 1 rənglə boyamaq olar. Əgər zirvəsinin atası varsa, onda onun oğlanları k - 2 rənglə boyanmalıdır. Çünki zirvəsinin oğlanları arasındakı məsafə -yə bərabərdir, onları eyni rənglərlə boyamaq olmaz.

Tutaq ki, müəyyənlik üçün zirvəsinin atası var. Onda zirvəsinin ilk oğlanını k - 2 rənglə, ikinci oğlanını k - 3 rənglə və s. boyamaq olar.

Hər zirvənin hansı rənglərlə boyanabileceyi hesablanmış rəng saylarını vurmaq qalır.

Nümunə

Birinci nümunə üçün boyama üsulu vardır:

İkinci testə nəzər salaq. Hər zirvənin yanında rəng sayı göstərək. Məsələn, zirvəsini 2 rənglə boyamaq olar, çünki onun rəngi və zirvələrinin rənglərinə uyğun olmamalıdır. Ağacı boyamağın ümumi üsulları 4 \cdot 3 \cdot 2 \cdot 1 \cdot 2 = 48-ə bərabərdir.

Alqoritmin realizasiyası

Girişdə verilən qraf qonşuluq siyahısında saxlanılır. sabiti – modulunu elan edirik.

#define MOD 1000000007
vector<vector<int>> g;

dfs funksiyası kökə zirvəsindən başlanan ağacın boyanma üsullarının sayını MOD = 10^9 + 7 modulu üzrə qaytarır. zirvəsinin atası -dir. zirvəsi rənglərlə boyana bilər.

int dfs(int v, int col, int p = -1)
{
  long long res = col;

Biz zirvəsində yerləşirik. zirvəsinin oğlanlarının hansı rənglərlə boyanmayacağını dəyişənində qeyd edirik. Əvvəlcə cnt = 1 qoyuruq, çünki zirvəsinin oğlanları zirvəsinin rəngi ilə eyni ola bilməz. Əgər zirvəsinin atası varsa (p \ne -1), onda zirvəsinin oğlanları -nin atasının rəngi ilə də eyni ola bilməz.

  int cnt = 1;
  if (p >= 0) cnt++;

zirvəsinin to oğlanlarını dolaşırıq.

  for (int to : g[v])
    if (to != p)
    {

to zirvəsi k - cnt rənglə boyana bilər. Hər oğlanla cnt dəyəri 1 artır.

      res = (res * dfs(to, k - cnt, v)) % MOD;
      cnt++;
    }
  return res;
}

Proqramın əsas hissəsi. Giriş məlumatlarını oxuyuruq.

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);
}

Dərinlik axtarışını zirvəsindən başlayırıq. zirvəsi rənglə boyana bilər.

res = dfs(1, k);

Cavabı ekrana çıxarırıq.

printf("%lld\n", res);

Python realizasiyası

Python interpretatorunun maksimum dərinliyini müəyyən edirik.

import sys
sys.setrecursionlimit(1000000)

sabitini – modulu elan edirik.

MOD = 1000000007

dfs funksiyası kökə zirvəsindən başlanan ağacın boyanma üsullarının sayını MOD = 10^9 + 7 modulu üzrə qaytarır. zirvəsinin atası -dir. zirvəsi rənglərlə boyana bilər.

def dfs(v, col, p = -1):
  res = col

Biz zirvəsində yerləşirik. zirvəsinin oğlanlarının hansı rənglərlə boyanmayacağını dəyişənində qeyd edirik. Əvvəlcə cnt = 1 qoyuruq, çünki zirvəsinin oğlanları zirvəsinin rəngi ilə eyni ola bilməz. Əgər zirvəsinin atası varsa (p \ne -1), onda zirvəsinin oğlanları -nin atasının rəngi ilə də eyni ola bilməz.

  cnt = 1
  if p >= 0: cnt += 1

zirvəsinin oğlanlarını dolaşırıq.

  for to in g[v]:
    if to != p:

to zirvəsi k - cnt rənglə boyana bilər. Hər oğlanla cnt dəyəri 1 artır.

      res = (res * dfs(to, k - cnt, v)) % MOD
      cnt += 1
  return res

Proqramın əsas hissəsi. Giriş məlumatlarını oxuyuruq.

n, k = map(int, input().split())
g = [[] for _ in range(n + 1)]
for _ in range(n - 1):
  a, b = map(int, input().split())
  g[a].append(b)
  g[b].append(a)

Dərinlik axtarışını zirvəsindən başlayırıq. zirvəsi rənglə boyana bilər.

res = dfs(1, k)

Cavabı ekrana çıxarırıq.

print(res)