У задачі потрібно виконати декомпозицію дерева на компоненти зв'язності з парним числом вершин. При цьому слід максимізувати кількість цих компонент.
Запустимо пошук у глибину з вершини , яка є коренем дерева. Для кожної вершини визначимо кількість вершин у піддереві з коренем . Якщо це число парне, то видалимо ребро, що з'єднує з його батьком при пошуку в глибину.
Для кореня (вершини ) розмір всього дерева парний. Проте ребра, що з'єднує вершину з її батьком, не існує. Тому з результату, отриманого за вищенаведеним алгоритмом, слід відняти .
Приклад
Розглянемо дерево, наведене в прикладі. Поруч із кожною вершиною зазначено розмір піддерева, якщо розглядати цю вершину як корінь. Вершини і мають піддерева з парним числом вершин. Оскільки вершина є коренем і не має ребра, що веде до батька, ми видаляємо два ребра: і .
Дерево розпалось на компоненти зв'язності, кожна з яких містить парне число вершин.
Реалізація алгоритму
Оголосимо робочі масиви.
#define MAX 101
int g[MAX][MAX], used[MAX];Функція dfs виконує пошук у глибину з вершини і повертає кількість вершин у піддереві з коренем .
int dfs(int v)
{
used[v] = 1;У змінній обчислюємо кількість вершин у піддереві з коренем .
int s = 1;Перебираємо синів вершини . Додаємо до значення .
for (int i = 1; i <= n; i++)
if (g[v][i] && !used[i]) s += dfs(i);Якщо розмір піддерева парний, видаляємо ребро між і його батьком.
if (s % 2 == 0) res++;Повертаємо кількість вершин у піддереві з коренем .
return s;
}Основна частина програми. Читаємо вхідні дані. Будуємо граф.
scanf("%d %d", &n, &m);
for (i = 0; i < m; i++)
{
scanf("%d %d", &a, &b);
g[a][b] = g[b][a] = 1;
}Запускаємо пошук у глибину з вершини . У змінній підраховуємо кількість видалених ребер.
res = 0;
dfs(1);Ребра з до її батька не існує. Виводимо res - 1.
printf("%d\n", res - 1);Python реалізація
Функція dfs виконує пошук у глибину з вершини і повертає кількість вершин у піддереві з коренем .
def dfs(v):
used[v] = 1У змінній обчислюємо кількість вершин у піддереві з коренем .
s = 1Перебираємо синів вершини . Додаємо до значення .
for i in range(1, n + 1):
if g[v][i] and not used[i]:
s += dfs(i)Якщо розмір піддерева парний, видаляємо ребро між і його батьком.
if s % 2 == 0:
global res
res += 1Повертаємо кількість вершин у піддереві з коренем .
return sОсновна частина програми. Читаємо вхідні дані. Будуємо граф.
n, m = map(int, input().split())
g = [[0] * (n + 1) for _ in range(n + 1)]
used = [0] * (n + 1)
for _ in range(m):
a, b = map(int, input().split())
g[a][b] = g[b][a] = 1Запускаємо пошук у глибину з вершини . У змінній підраховуємо кількість видалених ребер.
res = 0
dfs(1)Ребра з до її батька не існує. Виводимо res - 1.
print(res - 1)