Алгоритм прима минимальное покрывающее дерево

Алгоритм Прима

Алгоритм Прима (англ. Prim’s algorithm) — алгоритм поиска минимального остовного дерева (англ. minimum spanning tree, MST) во взвешенном неориентированном связном графе.

Идея

Данный алгоритм очень похож на алгоритм Дейкстры. Будем последовательно строить поддерево [math]F[/math] ответа в графе [math]G[/math] , поддерживая приоритетную очередь [math]Q[/math] из вершин [math]G \setminus F[/math] , в которой ключом для вершины [math]v[/math] является [math]\min\limits_w(uv)[/math] — вес минимального ребра из вершин [math]F[/math] в вершины [math]G \setminus F[/math] . Также для каждой вершины в очереди будем хранить [math]p(v)[/math] — вершину [math]u[/math] , на которой достигается минимум в определении ключа. Дерево [math]F[/math] поддерживается неявно, и его ребра — это пары [math]\left(v,p(v)\right)[/math] , где [math]v \in G \setminus \ \setminus Q[/math] , а [math]r[/math] — корень [math]F[/math] . Изначально [math]F[/math] пусто и значения ключей у всех вершин равны [math]+\infty[/math] . Выберём произвольную вершину [math]r[/math] и присвоим её ключу значение [math]0[/math] . На каждом шаге будем извлекать минимальную вершину [math]v[/math] из приоритетной очереди и релаксировать все ребра [math]vu[/math] , такие что [math]u \in Q[/math] , выполняя при этом операцию [math]\text[/math] над очередью и обновление [math]p(v)[/math] . Ребро [math]\left(v,p(v)\right)[/math] при этом добавляется к ответу.

Реализация

// [math]G[/math] — исходный граф // [math]w[/math] — весовая функция function [math]\mathtt():[/math] for [math]v \in V(G)[/math] [math]\mathtt[v]\ =\ \infty[/math] [math]\mathtt

[v]\ =[/math] null [math]r\ =[/math] произвольная вершина графа [math]G[/math] [math]\mathtt[r]\ =\ \mathtt[/math] [math]Q.\mathtt(V(G))[/math] while not [math]Q.\mathtt[/math] [math]v\ =\ Q.\mathtt()[/math] for [math]vu \in E(G)[/math] if [math]u \in Q[/math] and [math]\mathtt[u] \gt w(v, u)[/math] [math]\mathtt

[u]\ =\ v[/math] [math]\mathtt[u]\ =\ w(v, u)[/math] [math]Q.\mathtt(u, \mathtt[u])[/math]

Ребра дерева восстанавливаются из его неявного вида после выполнения алгоритма.
Чтобы упростить операцию [math]\mathrm[/math] можно написать кучу на основе сбалансированного бинарного дерева поиска. Тогда просто удалим вершину и добавим ее обратно уже с новым ключом. Асимптотика таких преобразований [math]O(\log n)[/math] . Если же делать с бинарной кучей, то вместо операции [math]\mathrm[/math] , будем всегда просто добавлять вершину с новым ключом, если из кучи достали вершину с ключом, значение которого больше чем у нее уже стоит, просто игнорировать. Вершин в куче будет не больше [math]n^2[/math] , следовательно, операция [math]\mathrm[/math] будет выполняться за [math]O(\log n^2)[/math] , что равно [math]O(\log n)[/math] . Максимальное количество вершин, которое мы сможем достать, равняется количеству ребер, то есть [math]m[/math] , поэтому общая асимптотика составит [math]O(m \log n)[/math] , что хорошо только на разреженных графах.

Пример

Рассмотрим работу алгоритма на примере графа. Пусть произвольно выбранная вершина — это вершина a.

Корректность

По поддерживаемым инвариантам после извлечения вершины [math]v\ (v \neq r)[/math] из [math]Q[/math] ребро [math]\left(v,p(v)\right)[/math] является ребром минимального веса, пересекающим разрез [math]\left(F,Q\right)[/math] . Значит, по лемме о безопасном ребре, оно безопасно. Алгоритм построения MST, добавляющий безопасные ребра, причём делающий это ровно [math]|V|-1[/math] раз, корректен.

Оценка производительности

Производительность алгоритма Прима зависит от выбранной реализации приоритетной очереди, как и в алгоритме Дейкстры. Извлечение минимума выполняется [math]V[/math] раз, релаксация — [math]O(E)[/math] раз.

Структура данных для приоритетной очереди Асимптотика времени работы
Наивная реализация [math]O(V^2+E)[/math]
Двоичная куча [math]O(E\log)[/math]
Фибоначчиева куча [math]O(V\log+E)[/math]

См. также

Источники информации

  • Томас Х. Кормен, Чарльз И. Лейзерсон, Рональд Л. Ривест, Клиффорд Штайн — Алгоритмы: построение и анализ, 2-е издание. Пер. с англ. — М.:Издательский дом «Вильямс», 2010. — с.653 — 656.— ISBN 978-5-8459-0857-5 (рус.)
  • Википедия — Алгоритм Прима
  • Wikipedia — Prim’s algorithm
  • MAXimal :: algo :: Минимальное остовное дерево. Алгоритм Прима

Источник

Алгоритм Прима

Алгоритм Прима (англ. Prim’s algorithm) — алгоритм поиска минимального остовного дерева (англ. minimum spanning tree, MST) во взвешенном неориентированном связном графе.

Идея

Данный алгоритм очень похож на алгоритм Дейкстры. Будем последовательно строить поддерево [math]F[/math] ответа в графе [math]G[/math] , поддерживая приоритетную очередь [math]Q[/math] из вершин [math]G \setminus F[/math] , в которой ключом для вершины [math]v[/math] является [math]\min\limits_w(uv)[/math] — вес минимального ребра из вершин [math]F[/math] в вершины [math]G \setminus F[/math] . Также для каждой вершины в очереди будем хранить [math]p(v)[/math] — вершину [math]u[/math] , на которой достигается минимум в определении ключа. Дерево [math]F[/math] поддерживается неявно, и его ребра — это пары [math]\left(v,p(v)\right)[/math] , где [math]v \in G \setminus \ \setminus Q[/math] , а [math]r[/math] — корень [math]F[/math] . Изначально [math]F[/math] пусто и значения ключей у всех вершин равны [math]+\infty[/math] . Выберём произвольную вершину [math]r[/math] и присвоим её ключу значение [math]0[/math] . На каждом шаге будем извлекать минимальную вершину [math]v[/math] из приоритетной очереди и релаксировать все ребра [math]vu[/math] , такие что [math]u \in Q[/math] , выполняя при этом операцию [math]\text[/math] над очередью и обновление [math]p(v)[/math] . Ребро [math]\left(v,p(v)\right)[/math] при этом добавляется к ответу.

Реализация

// [math]G[/math] — исходный граф // [math]w[/math] — весовая функция function [math]\mathtt():[/math] for [math]v \in V(G)[/math] [math]\mathtt[v]\ =\ \infty[/math] [math]\mathtt

[v]\ =[/math] null [math]r\ =[/math] произвольная вершина графа [math]G[/math] [math]\mathtt[r]\ =\ \mathtt[/math] [math]Q.\mathtt(V(G))[/math] while not [math]Q.\mathtt[/math] [math]v\ =\ Q.\mathtt()[/math] for [math]vu \in E(G)[/math] if [math]u \in Q[/math] and [math]\mathtt[u] \gt w(v, u)[/math] [math]\mathtt

[u]\ =\ v[/math] [math]\mathtt[u]\ =\ w(v, u)[/math] [math]Q.\mathtt(u, \mathtt[u])[/math]

Ребра дерева восстанавливаются из его неявного вида после выполнения алгоритма.
Чтобы упростить операцию [math]\mathrm[/math] можно написать кучу на основе сбалансированного бинарного дерева поиска. Тогда просто удалим вершину и добавим ее обратно уже с новым ключом. Асимптотика таких преобразований [math]O(\log n)[/math] . Если же делать с бинарной кучей, то вместо операции [math]\mathrm[/math] , будем всегда просто добавлять вершину с новым ключом, если из кучи достали вершину с ключом, значение которого больше чем у нее уже стоит, просто игнорировать. Вершин в куче будет не больше [math]n^2[/math] , следовательно, операция [math]\mathrm[/math] будет выполняться за [math]O(\log n^2)[/math] , что равно [math]O(\log n)[/math] . Максимальное количество вершин, которое мы сможем достать, равняется количеству ребер, то есть [math]m[/math] , поэтому общая асимптотика составит [math]O(m \log n)[/math] , что хорошо только на разреженных графах.

Пример

Рассмотрим работу алгоритма на примере графа. Пусть произвольно выбранная вершина — это вершина a.

Корректность

По поддерживаемым инвариантам после извлечения вершины [math]v\ (v \neq r)[/math] из [math]Q[/math] ребро [math]\left(v,p(v)\right)[/math] является ребром минимального веса, пересекающим разрез [math]\left(F,Q\right)[/math] . Значит, по лемме о безопасном ребре, оно безопасно. Алгоритм построения MST, добавляющий безопасные ребра, причём делающий это ровно [math]|V|-1[/math] раз, корректен.

Оценка производительности

Производительность алгоритма Прима зависит от выбранной реализации приоритетной очереди, как и в алгоритме Дейкстры. Извлечение минимума выполняется [math]V[/math] раз, релаксация — [math]O(E)[/math] раз.

Структура данных для приоритетной очереди Асимптотика времени работы
Наивная реализация [math]O(V^2+E)[/math]
Двоичная куча [math]O(E\log)[/math]
Фибоначчиева куча [math]O(V\log+E)[/math]

См. также

Источники информации

  • Томас Х. Кормен, Чарльз И. Лейзерсон, Рональд Л. Ривест, Клиффорд Штайн — Алгоритмы: построение и анализ, 2-е издание. Пер. с англ. — М.:Издательский дом «Вильямс», 2010. — с.653 — 656.— ISBN 978-5-8459-0857-5 (рус.)
  • Википедия — Алгоритм Прима
  • Wikipedia — Prim’s algorithm
  • MAXimal :: algo :: Минимальное остовное дерево. Алгоритм Прима

Источник

Минимальное остовное дерево. Алгоритм Прима. Алгоритм Крускала

Остовным деревом графа называется дерево, которое можно получить из него путём удаления некоторых рёбер. У графа может существовать несколько остовных деревьев, и чаще всех их достаточно много.

Остовное дерево графа-решётки

На иллюстрации приведено одно из остовных деревьев (рёбра выделены синим цветом) решёткообразного графа.

Для взвешенных графов существует понятие веса остовного дерева, которое определено как сумма весов всех рёбер, входящих в остовное дерево. Из него натурально вытекает понятие минимального остовного дерева — остовного дерева с минимальным возможным весом.

Граф с выделенным минимальным остовным деревом

Для нахождения минимального остовного дерева графа существуют два основных алгоритма: алгоритм Прима и алгоритм Крускала. Они оба имеют сложность \(O(M \log N)\), поэтому выбор одного из них зависит от ваших личных предпочтений. В этой лекции мы разберём оба.

Алгоритм Прима

Алгоритм Прима в идее и реализации очень похож на алгоритм Дейкстры. Как и в алгоритме Дейкстры, мы поддерживаем уже обработанную часть графа (минимального остовного дерева), и постепенно её расширяем за счёт ближайших вершин.

Утверждается, что если разделить вершины графа на два множества (обработанные и необработанные), первое из которых составляет связную часть минимального остовного дерева, то ребро минимальной длины, связывающее эти два множества гарантированно будет входить в минимальное остовное дерево.

Таким образом, для нахождения минимального остовного дерева начнём с произвольной вершины и будем постепенно добавлять ближайшие к уже имеющимся.

На иллюстрации красным цветом выделены рёбра, уже вошедшие в минимальный остов, а чёрным — текущие кандидаты, из которых выбирается ребро с минимальным весом.

Реализация алгоритма Прима

Будем искать вес минимального остовного дерева. Для нахождения ближайшей вершины воспользуемся очередью с приоритетом (аналогично алгоритму Дейкстры), в которой будем хранить пары (расстояние от остова до вершины, номер вершины).

Различия в скорости работы

Хотя оба алгоритма работают за \(O(M \log N)\), существуют константные различия в скорости их работы. На разреженных графах (количество рёбер примерно равно количеству вершин) быстрее работает алгоритм Крускала, а на насыщенных (количество рёбер примерно равно квадрату количеству вершин) — алгоритм Прима (при использовании матрицы смежности).

На практике чаще используется алгоритм Крускала.

brestprog

Олимпиадное программирование в Бресте и Беларуси

Источник

Читайте также:  Деревья своими руками клен
Оцените статью