Вклад ребра
Сумму по всем парам вершин не обязательно считать перебором пар. Часто дешевле спросить у каждого ребра, в скольких парах оно участвует.
2 мин
Задачи вида «посчитать что-то по всем парам вершин» выглядят квадратично: пар , и при это .
Спасает смена точки зрения: вместо «переберём пары и для каждой посчитаем длину пути» - «переберём рёбра и для каждого посчитаем, во скольких путях оно участвует».
Сколько путей проходит через ребро
Дерево (или лес). Удалим ребро - дерево распадётся на две части размеров и . Простой путь проходит через ровно тогда, когда его концы лежат в разных частях.
Размеры считаются одним обходом: если подвесить дерево за корень, то для ребра «вершина - её предок» части равны и .
Что из этого следует
Сумма длин всех путей равна сумме вкладов рёбер:
Каждое ребро на пути добавляет к его длине единицу, значит суммарная длина - это просто «сколько раз каждое ребро было пройдено».
Количество путей в лесу - это сумма по компонентам размера : путь существует ровно между вершинами одной компоненты.
long long paths = 0, lengths = 0;
for (long long s : componentSizes) paths += s * (s - 1) / 2;
for (int v : vertices) if (parent[v] >= 0)
lengths += sub[v] * (componentSize[v] - sub[v]);
Проверено: на 4000 случайных лесов до 9 вершин обе величины совпали с прямым перебором всех пар и обходом из каждой вершины.
Про типы
При количество путей доходит до , а сумма длин - до у пути-цепочки. Оба числа не помещаются в 32 бита; произведение тоже надо считать в 64-битном типе, даже если сами и - int.
Где ещё работает тот же приём
Смена точки зрения с «объектов» на «вклады» встречается далеко за пределами деревьев:
| задача | что перебирать вместо пар |
|---|---|
| сумма длин путей в дереве | рёбра |
| сумма минимумов по всем подотрезкам | элементы: в скольких подотрезках элемент минимален |
| сумма попарных расстояний на прямой | промежутки между соседними точками |
| количество инверсий | элементы: сколько меньших справа |
Общий признак: величина по паре раскладывается в сумму по «мелким» объектам, и для каждого мелкого объекта легко посчитать, в скольких парах он участвует.