Найкоротший шлях у зваженому дереві можна знайти за допомогою пошуку в глибину або в ширину (використання алгоритму Дейкстри в даному випадку не є обов'язковим).
Для знаходження найдовшого шляху (діаметра дерева) діємо наступним чином:
Виконаємо пошук в ширину з першої вершини. Знайдемо вершину , до якої шлях буде найбільшим.
Потім запустимо пошук в ширину з вершини і визначимо вершину , до якої шлях також буде найбільшим.
Шлях від до є найдовшим у дереві (діаметром дерева).
Приклад
Дерево, представлене у прикладі, має наступний вигляд:
Виконаємо пошук в ширину з вершини (зліва). Найдовший шлях буде до вершини .
Потім запустимо пошук в ширину з вершини (справа). Найдовший шлях виявиться до вершини , його довжина рівна .
Реалізація алгоритму
Оголосимо список суміжності графа .
Оголосимо масив найкоротших відстаней .
vector\<vector\<pair\<int, int\>\> \> g;
vector\<long long\> d;Функція bfs виконує пошук в ширину з вершини .
int bfs(int v)
{
deque\<int\> q;
q.push_back(v);
while (!q.empty())
{
int v = q.front(); q.pop_front();
for (auto x : g[v])
{
int to = x.first;
int w = x.second;
if (d[to] == -1)
{
d[to] = d[v] + w;
q.push_back(to);
}
}
}Повертаємо номер вершини, до якої відстань від вершини максимальна.
return max_element(d.begin() + 1, d.begin() + n + 1) - d.begin();
}Основна частина програми. Читаємо вхідні дані. Будуємо граф.
scanf("%d", \&n);
g.resize(n + 1);
for (i = 0; i \< n - 1; i++)
{
scanf("%d %d %lld", \&b, \&e, \&dist);
g[b].push_back({ e, dist });
g[e].push_back({ b, dist });
}Ініціалізуємо масив найкоротших відстаней.
d = vector\<long long\>(n + 1, -1);
d[1] = 0;Виконуємо перший пошук в ширину з вершини . Визначаємо вершину , яка знаходиться найдалі від .
int v = bfs(1);Знову ініціалізуємо масив найкоротших відстаней і запускаємо другий пошук в ширину, починаючи з вершини .
d = vector\<long long\>(n + 1, -1);
d[v] = 0;
v = bfs(v);Виводимо відповідь — довжину найбільшого шляху.
printf("%lld\n", d[v]);Реалізація алгоритму — пошук в глибину
Список суміжності графа зберігаємо в масиві .
Для зберігання найкоротших відстаней оголосимо масив .
vector\<vector\<pair\<int, int\>\> \> g;
vector\<long long\> dist;Функція dfs виконує пошук в глибину з вершини . Вершина є предком у процесі пошуку в глибину.
void dfs(int v, int p = -1)
{Перебираємо всі ребра, суміжні з вершиною .
for (auto x : g[v])
{Розглядаємо ребро v → to з вагою .
int to = x.first;
int w = x.second;Якщо to \ne p, перераховуємо dist[to] і викликаємо пошук в глибину з вершини .
if (to != p)
{
dist[to] = dist[v] + w;
dfs(to, v);
}
}
}Основна частина програми. Читаємо вхідні дані. Будуємо граф.
scanf("%d", \&n);
g.resize(n + 1);
for (i = 0; i \< n - 1; i++)
{
scanf("%d %d %d", \&b, \&e, \&w);
g[b].push_back({ e, w });
g[e].push_back({ b, w });
}Виконуємо пошук в глибину з вершини . Заповнюємо масив найкоротших відстаней від вершини .
dist.assign(n + 1, -1);
dist[1] = 0;
dfs(1);Визначаємо вершину , відстань до якої від вершини максимальна.
v = max_element(dist.begin(), dist.end()) - dist.begin();Виконуємо другий пошук в глибину, починаючи з вершини . Заповнюємо масив найкоротших відстаней від вершини .
dist.assign(n + 1, -1);
dist[v] = 0;
dfs(v);Найбільше значення в масиві дорівнює діаметру дерева.
v = max_element(dist.begin(), dist.end()) - dist.begin();Виводимо відповідь.
printf("%lld\n", dist[v]);Python реалізація
from collections import dequeЧитаємо вхідні дані. Список суміжності графа зберігаємо в .
Оголошуємо список найкоротших відстаней .
n = int(input())
g = [[] for _ in range(n + 1)]
d = [-1] * (n + 1)Будуємо граф.
for _ in range(n - 1):
b, e, dist = map(int, input().split())
g[b].append((e, dist))
g[e].append((b, dist))Функція bfs виконує пошук в ширину з вершини .
def bfs(v):
q = deque()
q.append(v)
while q:
v = q.popleft()
for to, w in g[v]:
if d[to] == -1:
d[to] = d[v] + w
q.append(to)Повертаємо номер вершини, до якої відстань від вершини максимальна.
return d.index(max(d))Виконуємо перший пошук в ширину з вершини . Визначаємо вершину , яка знаходиться найдалі від .
d[1] = 0
v = bfs(1)Ініціалізуємо масив найкоротших відстаней і запускаємо другий пошук в ширину з вершини .
d = [-1] * (n + 1)
d[v] = 0
v = bfs(v)Виводимо відповідь — довжину найбільшого шляху.
print(d[v])