Знайти пари#11609

Знайти пари (Розбір)

Умова d(i, j) = d(i, 1) - d(j, 1) виконується для кожної пари вершин , у якої є предком при пошуку в глибину з вершини . Розглянемо приклад:

Глибиною вершини назвемо кількість вершин на шляху від кореня (вершини ) до . На малюнку глибина вказана біля кожної вершини.

Зафіксуємо вершину і відповімо на питання: скільки існує вершин , для яких виконується умова 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);