Розв'язок
Початкова мережа доріг є деревом. Нам потрібно додати одне ребро між двома несуміжними вершинами так, щоб мінімізувати сумарну шкоду від незалежного видалення кожного початкового ребра.
Розглянемо додавання ребра між вершинами та .
Оскільки початковий граф є деревом, між та існує рівно один простий шлях. Додавання нового ребра утворює цикл, який складається з цього шляху та нового ребра.
Якщо видалити початкове ребро, яке належить цьому циклу, граф залишиться зв'язним, тому шкода дорівнюватиме .
В іншому випадку видалення початкового ребра розбиває граф на дві компоненти зв'язності. Якщо їхні розміри дорівнюють та n-s, шкода становитиме
Зауважимо, що ця величина не залежить від того, яке нове ребро ми додамо, якщо видалене ребро не належить утвореному циклу.
Підвісимо початкове дерево за вершину . Нехай sz_v — розмір піддерева вершини .
Для кожного ребра, яке з'єднує вершину з її батьком, визначимо вагу
Позначимо через суму ваг усіх початкових ребер:
Якщо додати ребро між вершинами та , усі початкові ребра на шляху між ними належатимуть утвореному циклу та даватимуть внесок у сумарну шкоду.
Тому сумарна шкода після додавання цього ребра дорівнюватиме
Отже, мінімізація сумарної шкоди еквівалентна пошуку шляху з максимальною можливою сумою ваг ребер.
Це задача пошуку зваженого діаметра дерева.
Нехай — максимальна сума ваг ребер уздовж простого шляху. Тоді відповідь дорівнює
Оскільки всі ваги ребер додатні та n\ge 3, зважений діаметр містить щонайменше два ребра. Отже, його кінцеві вершини не є суміжними, тому додавання ребра між ними завжди дозволене.
Знайдемо зважений діаметр за допомогою динамічного програмування на дереві.
Нехай dp_v — максимальна сума ваг ребер на шляху, який починається у вершині та йде вниз у її піддерево.
Для кожного сина вершини розглянемо значення
Нехай best_1 та best_2 — два найбільші значення серед цих кандидатів. Якщо синів менше ніж два, відсутні значення вважатимемо рівними .
Тоді
Максимальна вага шляху, найвищою вершиною якого є , дорівнює
Отже, зважений діаметр дерева можна знайти за формулою
Розміри піддерев, суму ваг та зважений діаметр обчислимо за один обхід підвішеного дерева знизу вгору.
Асимптотична складність
Побудова підвішеного дерева займає часу. Кожне ребро обробляється сталу кількість разів під час обчислення розмірів піддерев та зваженого діаметра.
Отже, загальна часова складність становить , а просторова — .
Реалізація
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
void solve() {
int n;
cin >> n;
vector<vector<int>> g(n + 1);
for (int i = 1; i < n; i++) {
int u, v;
cin >> u >> v;
g[u].push_back(v);
g[v].push_back(u);
}
vector<int> par(n + 1), order;
order.push_back(1);
for (int i = 0; i < (int)order.size(); i++) {
int v = order[i];
for (int u : g[v]) {
if (u == par[v]) continue;
par[u] = v;
order.push_back(u);
}
}
vector<int> sz(n + 1, 1);
vector<ll> dp(n + 1);
ll sum = 0, diam = 0;
for (int i = n - 1; i >= 0; i--) {
int v = order[i];
ll best1 = 0, best2 = 0;
for (int u : g[v]) {
if (par[u] != v) continue;
sz[v] += sz[u];
ll w = min(sz[u], n - sz[u]);
sum += w;
ll cur = dp[u] + w;
if (cur > best1) {
best2 = best1;
best1 = cur;
} else if (cur > best2) {
best2 = cur;
}
}
dp[v] = best1;
diam = max(diam, best1 + best2);
}
cout << sum - diam << '\n';
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
solve();
}