Кефа і парк#11153

Кефа і парк (Розбір)

Запустим пошук вглиб з вершини , де знаходиться дім Кефи. В одному з параметрів функції dfs будемо зберігати кількість поспіль вершин з котами. Якщо у вершині це число перевищить , подальший пошук вглиб з цієї вершини не виконуємо. Підраховуємо кількість відвідуваних листків. Вершина є листком, якщо її ступінь дорівнює і при цьому вона не є коренем (тобто вершиною ).

Приклад

Розглянемо дерева з першого та другого прикладів.

У першому прикладі Кефа може пройти поспіль тільки через одну вершину з котом. Він зможе потрапити у ресторани, розташовані у вершинах та .

У другому прикладі Кефа може пройти поспіль тільки через дві вершини з котами. Він зможе потрапити у ресторани, розташовані у вершинах та .

Реалізація алгоритму

Розташування котів зберігаємо в масиві . Дерево зберігаємо у списку суміжності .

vector<int> cats;
vector<vector<int> > g;

Функція dfs виконує пошук вглиб з вершини і повертає кількість ресторанів, до яких можна дістатися з цієї вершини (за умови що на шляху до них зустрічається не більше поспіль вершин з котами). Попередником вершини є вершина . Кількість поспіль вершин з котами, пройдених включно до вершини , дорівнює .

int dfs(int v, int prev, int cnt)
{

Якщо вже пройдено більше котів поспіль, то подальший пошук вглиб з вершини не продовжується.

  if (cnt > m) return 0;

Якщо ми знаходимося у листі, то збільшуємо кількість ресторанів, до яких можна потрапити.

  if (g[v].size() == 1 && prev != -1) return 1;

У змінній підраховуємо кількість ресторанів, досяжних з вершини .

  int res = 0;

Перебираємо всі ребра (v, to), що виходять з . Якщо вершина є попередником , то не переходимо в цю вершину.

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

Якщо у вершині немає кота, встановлюємо c = 0. У противному випадку присвоюємо c = cnt + 1. Змінна зберігає кількість поспіль вершин з котами до вершини включно.

      int c = (cats[to] == 0) ? 0 : cnt + 1;

Запускаємо пошук вглиб з вершини .

      res += dfs(to, v, c);
    }

Повертаємо результат.

  return res;
}

Основна частина програми. Читаємо вхідні дані.

scanf("%d %d", &n, &m);
cats.resize(n + 1);
for (i = 1; i <= n; i++)
  scanf("%d", &cats[i]);

Будуємо дерево.

g.resize(n + 1);
for (i = 1; i < n; i++)
{
  scanf("%d %d", &a, &b);
  g[a].push_back(b);
  g[b].push_back(a);
}

Виводимо відповідь. Функція dfs, викликана з вершини , повертає відповідь на задачу. Оскільки у вершини немає предка, другим параметром передаємо значення . Розпочавши з вершини , ми відвідали котів.

printf("%d\n", dfs(1, -1, cats[1]));

Python реалізація

Функція dfs виконує пошук вглиб з вершини і повертає кількість ресторанів, до яких можна дістатися з цієї вершини (за умови що на шляху до них зустрічається не більше поспіль вершин з котами). Попередником вершини є вершина . Кількість поспіль вершин з котами, пройдених включно до вершини , дорівнює .

def dfs(v, prev, cnt):

Якщо вже пройдено більше котів поспіль, то подальший пошук вглиб з вершини не продовжується.

  if cnt > m:
    return 0

Якщо ми знаходимося у листі, то збільшуємо кількість ресторанів, до яких можна потрапити.

  if len(g[v]) == 1 and prev != -1:
    return 1

У змінній підраховуємо кількість ресторанів, досяжних з вершини .

  res = 0

Перебираємо всі ребра (v, to), що виходять з . Якщо вершина є попередником , то не переходимо в цю вершину.

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

Якщо у вершині немає кота, встановлюємо c = 0. У противному випадку присвоюємо c = cnt + 1. Змінна зберігає кількість поспіль вершин з котами до вершини включно.

      c = 0 if cats[to] == 0 else cnt + 1

Запускаємо пошук вглиб з вершини .

      res += dfs(to, v, c)

Повертаємо результат.

  return res

Основна частина програми. Читаємо вхідні дані.

n, m = map(int, input().split())
cats = [0] + list(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)

Виводимо відповідь. Функція dfs, викликана з вершини , повертає відповідь на задачу. Оскільки у вершини немає предка, другим параметром передаємо значення . Розпочавши з вершини , ми відвідали котів.

print(dfs(1, -1, cats[1]))