Умова d(i, j) = d(i, 1) - d(j, 1) виконується для кожної пари вершин , у якої є предком при пошуку в глибину з вершини . Розглянемо приклад:
d(4, 1) = 2, d(4, 1) - d(1, 1) = 2 - 0 = 2;
d(6, 3) = 2, d(6, 1) - d(3, 1) = 3 - 1 = 2;
d(2, 2) = 0, d(2, 1) - d(2, 1) = 1 - 1 = 0;
d(6, 1) = 3, d(6, 1) - d(1, 1) = 3 - 0 = 3;
Глибиною вершини назвемо кількість вершин на шляху від кореня (вершини ) до . На малюнку глибина вказана біля кожної вершини.
Зафіксуємо вершину і відповімо на питання: скільки існує вершин , для яких виконується умова d(i, j) = d(i, 1) - d(j, 1).
Наприклад, для i = 6 існують такі вершини: j = 1, 3, 4, 6. Зазначимо, що h[6] = 4. Таким чином, для фіксованої вершини існує рівно підходящих вершин .
Для розв'язання задачі необхідно для кожної вершини дерева обчислити її глибину , а потім знайти суму всіх значень глибин по дереву.
Приклад
Розглянемо граф з прикладу. Біля кожної вершини запишемо її глибину.
Сума глибин всіх вершин дорівнює 1 + 2 + 3 + 3 + 4 = 13.
Реалізація алгоритму
Оголосимо список суміжності графа . Глибину вершин зберігаємо в масиві .
vector<vector<int> > g;
vector<int> h;Функція dfs для кожної вершини обчислює її глибину. Предком вершини є вершина .
int dfs(int v, int p)
{
for (int to : g[v])Розглядаємо ребро (v, to). Якщо вершина не є предком вершини , обчислюємо її глибину і запускаємо з неї пошук в глибину.
if (to != p)
{
h[to] = h[v] + 1;
dfs(to, v);
}
return h[v];
}Основна частина програми. Зчитуємо кількість вершин дерева .
scanf("%d", &n);
g.resize(n + 1);Будуємо дерево.
for (i = 2; i <= n; i++)
{
scanf("%d %d", &a, &b);
g[a].push_back(b);
g[b].push_back(a);
}Глибину вершини покладемо рівною .
h.resize(n + 1);
h[1] = 1;Запускаємо пошук в глибину, починаючи з вершини .
dfs(1, -1);Обчислюємо відповідь — суму глибин всіх вершин.
res = 0;
for (i = 1; i <= n; i++)
res += h[i];Виводимо відповідь.
printf("%lld\n", res);