11609. Найти
пары
Задано дерево с n вершинами. Вершина 1 является корнем. Между любыми двумя вершинами существует единственный путь.
Определим d(i, j) как
количество ребер на пути между вершинами i и j.
Найдите количество таких пар (i, j), что d(i, j) = d(i, 1) – d(j, 1).
Вход. Первая строка содержит количество вершин n (1 ≤ n ≤ 105) в дереве. Каждая из следующих n – 1 строк задает ребро дерева.
Выход. Выведите количество таких пар (i, j), что d(i, j) = d(i, 1) – d(j, 1).
Пример
входа |
Пример
выхода |
5 1 2 2 3 2 4 4 5 |
13 |
графы –
поиск в глубину
Условие d(i, j) = d(i, 1) – d(j, 1) справедливо для всякой пары (i, j), у которой j является
предком i при поиске в глубину из вершины 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;
Глубиной h[v] вершины v назовем количество
вершин на пути из 1 в v. На рисунке глубина
указана возле каждой вершины. Зафиксируем вершину i и ответим на
вопрос: сколько существует вершин j, что d(i, j) = d(i, 1) – d(j, 1).
Например, для i = 6 существуют
4 такие вершины: j = 1, 3,
4, 6. Отметим, что h[6] = 4. Для
фиксированного значения i существует в точности h[i] соответствующих
значений j.
Для решения
задачи следует для каждой вершины v дерева найти ее глубину h[v] и вычислить
сумму глубин по всем вершинам.
Пример
Рассмотрим граф из примера. Возле каждой вершины запишем ее глубину.
Сумма глубин всех
вершин равна 1 + 2 + 3 + 3 +
4 = 13.
Реализация алгоритма
Объявим список смежности графа g. Глубину вершин храним в массиве h.
vector<vector<int> > g;
vector<int> h;
Функция dfs для каждой вершины v вычисляет ее глубину. Предком v является вершина p.
int dfs(int v, int p)
{
for (int to : g[v])
Обрабатываем ребро (v, to). Если to не является предком v, то вычисляем глубину
to и запускаем из to поиск в глубину.
if (to != p)
{
h[to] = h[v] + 1;
dfs(to, v);
}
return h[v];
}
Основная часть программы. Читаем количество вершин дерева n.
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);
}
Высоту вершины 1 положим равной 1.
h.resize(n + 1);
h[1] = 1;
Запускаем поиск в глубину из вершины 1.
dfs(1, -1);
Вычисляем ответ – сумму глубин всех вершин.
res = 0;
for (i = 1; i <= n; i++)
res += h[i];
Выводим ответ.
printf("%lld\n", res);