<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ru">
		<id>http://neerc.ifmo.ru/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=5.45.192.105&amp;*</id>
		<title>Викиконспекты - Вклад участника [ru]</title>
		<link rel="self" type="application/atom+xml" href="http://neerc.ifmo.ru/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=5.45.192.105&amp;*"/>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%BB%D1%83%D0%B6%D0%B5%D0%B1%D0%BD%D0%B0%D1%8F:%D0%92%D0%BA%D0%BB%D0%B0%D0%B4/5.45.192.105"/>
		<updated>2026-04-09T17:49:50Z</updated>
		<subtitle>Вклад участника</subtitle>
		<generator>MediaWiki 1.30.0</generator>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9F%D1%80%D0%B8%D0%BC%D0%B0&amp;diff=40582</id>
		<title>Алгоритм Прима</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9F%D1%80%D0%B8%D0%BC%D0%B0&amp;diff=40582"/>
				<updated>2014-11-01T16:48:44Z</updated>
		
		<summary type="html">&lt;p&gt;5.45.192.105: /* Пример */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Алгоритм Прима''' (англ. ''Prim's algorithm'') — алгоритм поиска [[Лемма о безопасном ребре#Минимальное остовное дерево|минимального остовного дерева]] (англ. ''minimum spanning tree, MST'') во взвешенном [[Основные определения теории графов#Неориентированные графы | неориентированном связном графе]].&lt;br /&gt;
&lt;br /&gt;
== Идея ==&lt;br /&gt;
Данный алгоритм очень похож на [[алгоритм Дейкстры]]. Будем последовательно строить поддерево &amp;lt;tex&amp;gt;F&amp;lt;/tex&amp;gt; ответа в графе &amp;lt;tex&amp;gt;G&amp;lt;/tex&amp;gt;, поддерживая [[Дискретная_математика,_алгоритмы_и_структуры_данных#.D0.9F.D1.80.D0.B8.D0.BE.D1.80.D0.B8.D1.82.D0.B5.D1.82.D0.BD.D1.8B.D0.B5_.D0.BE.D1.87.D0.B5.D1.80.D0.B5.D0.B4.D0.B8 | приоритетную очередь]] &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt; из вершин &amp;lt;tex&amp;gt;G \setminus F&amp;lt;/tex&amp;gt;, в которой ключом для вершины &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; является &amp;lt;tex&amp;gt;\min\limits_{u \in V(F), uv \in E(G)}w(uv)&amp;lt;/tex&amp;gt; — вес минимального ребра из вершин &amp;lt;tex&amp;gt;F&amp;lt;/tex&amp;gt; в вершины &amp;lt;tex&amp;gt;G \setminus F&amp;lt;/tex&amp;gt;. Также для каждой вершины в очереди будем хранить &amp;lt;tex&amp;gt;p(v)&amp;lt;/tex&amp;gt; — вершину &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt;, на которой достигается минимум в определении ключа. Дерево &amp;lt;tex&amp;gt;F&amp;lt;/tex&amp;gt; поддерживается неявно, и его ребра — это пары &amp;lt;tex&amp;gt;\left(v,p(v)\right)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;v \in G \setminus \{r\} \setminus Q&amp;lt;/tex&amp;gt;, а &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt; — корень &amp;lt;tex&amp;gt;F&amp;lt;/tex&amp;gt;. Изначально &amp;lt;tex&amp;gt;F&amp;lt;/tex&amp;gt; пусто и значения ключей у всех вершин равны &amp;lt;tex&amp;gt;+\infty&amp;lt;/tex&amp;gt;. Выберём произвольную вершину &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt; и присвоим её ключу значение &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;. На каждом шаге будем извлекать минимальную вершину &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; из приоритетной очереди и релаксировать все ребра &amp;lt;tex&amp;gt;vu&amp;lt;/tex&amp;gt;, такие что &amp;lt;tex&amp;gt;u \in Q&amp;lt;/tex&amp;gt;, выполняя при этом операцию &amp;lt;tex&amp;gt;\text{decreaseKey}&amp;lt;/tex&amp;gt; над очередью и обновление &amp;lt;tex&amp;gt;p(v)&amp;lt;/tex&amp;gt;. Ребро &amp;lt;tex&amp;gt;\left(v,p(v)\right)&amp;lt;/tex&amp;gt; при этом добавляется к ответу.&lt;br /&gt;
&lt;br /&gt;
== Реализация ==&lt;br /&gt;
 &amp;lt;font color=green&amp;gt;// &amp;lt;tex&amp;gt;G&amp;lt;/tex&amp;gt; {{---}} исходный граф&amp;lt;/font&amp;gt;&lt;br /&gt;
 &amp;lt;font color=green&amp;gt;// &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt; {{---}} весовая функция&amp;lt;/font&amp;gt;&lt;br /&gt;
 '''function''' &amp;lt;tex&amp;gt;\mathtt{primFindMST}():&amp;lt;/tex&amp;gt;&lt;br /&gt;
    '''for''' &amp;lt;tex&amp;gt;v \in V(G)&amp;lt;/tex&amp;gt;&lt;br /&gt;
        &amp;lt;tex&amp;gt;\mathtt{key}[v]\ =\ \infty&amp;lt;/tex&amp;gt;&lt;br /&gt;
        &amp;lt;tex&amp;gt;\mathtt{p}[v]\ =&amp;lt;/tex&amp;gt; ''null''&lt;br /&gt;
    &amp;lt;tex&amp;gt;r\ =&amp;lt;/tex&amp;gt; произвольная вершина графа &amp;lt;tex&amp;gt;G&amp;lt;/tex&amp;gt;&lt;br /&gt;
    &amp;lt;tex&amp;gt;\mathtt{key}[r]\ =\ \mathtt{0}&amp;lt;/tex&amp;gt; &lt;br /&gt;
    &amp;lt;tex&amp;gt;Q.\mathtt{push}(V(G))&amp;lt;/tex&amp;gt; &lt;br /&gt;
    '''while not''' &amp;lt;tex&amp;gt;Q.\mathtt{isEmpty()}&amp;lt;/tex&amp;gt;&lt;br /&gt;
        &amp;lt;tex&amp;gt;v\ =\ Q.\mathtt{extractMin}()&amp;lt;/tex&amp;gt; &lt;br /&gt;
        '''for''' &amp;lt;tex&amp;gt;vu \in E(G)&amp;lt;/tex&amp;gt;&lt;br /&gt;
            '''if''' &amp;lt;tex&amp;gt;u \in Q&amp;lt;/tex&amp;gt; '''and''' &amp;lt;tex&amp;gt;\mathtt{key}[u] &amp;gt; w(v, u)&amp;lt;/tex&amp;gt;&lt;br /&gt;
                &amp;lt;tex&amp;gt;\mathtt{p}[u]\ =\ v&amp;lt;/tex&amp;gt;&lt;br /&gt;
                &amp;lt;tex&amp;gt;\mathtt{key}[u]\ =\ w(v, u)&amp;lt;/tex&amp;gt;&lt;br /&gt;
                &amp;lt;tex&amp;gt;Q.\mathtt{decreaseKey}(u, \mathtt{key}[u])&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ребра дерева восстанавливаются из его неявного вида после выполнения алгоритма.&amp;lt;br&amp;gt;&lt;br /&gt;
Чтобы упростить операцию &amp;lt;tex&amp;gt;\mathrm{decreaseKey}&amp;lt;/tex&amp;gt; можно написать кучу на основе [[АВЛ-дерево | сбалансированного бинарного дерева поиска]]. Тогда просто удалим вершину и добавим ее обратно уже с новым ключом. Асимптотика таких преобразований &amp;lt;tex&amp;gt;O(\log n)&amp;lt;/tex&amp;gt;. Если же делать с [[Двоичная_куча | бинарной кучей]], то вместо операции &amp;lt;tex&amp;gt;\mathrm{decreaseKey}&amp;lt;/tex&amp;gt;, будем всегда просто добавлять вершину с новым ключом, если из кучи достали вершину с ключом, значение которого больше чем у нее уже стоит, просто игнорировать. Вершин в куче будет не больше &amp;lt;tex&amp;gt;n^2&amp;lt;/tex&amp;gt;, следовательно, операция &amp;lt;tex&amp;gt;\mathrm{extractMin}&amp;lt;/tex&amp;gt; будет выполняться за &amp;lt;tex&amp;gt;O(\log n^2)&amp;lt;/tex&amp;gt;, что равно &amp;lt;tex&amp;gt;O(\log n)&amp;lt;/tex&amp;gt;. Максимальное количество вершин, которое мы сможем достать, равняется количеству ребер, то есть &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt;, поэтому общая асимптотика составит &amp;lt;tex&amp;gt;O(m \log n)&amp;lt;/tex&amp;gt;, что хорошо только на разреженных графах.&lt;br /&gt;
&lt;br /&gt;
==Пример==&lt;br /&gt;
Рассмотрим работу алгоритма на примере графа.&lt;br /&gt;
Пусть произвольно выбранная вершина — это вершина a.&lt;br /&gt;
{| cellpadding = &amp;quot;20&amp;quot; class = &amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Изображение !! Множество вершин !! Описание&lt;br /&gt;
|-&lt;br /&gt;
|[[Файл:Mst_prima_1.png|200px]]&lt;br /&gt;
|&lt;br /&gt;
{| width=&amp;quot;100%&amp;quot; style = &amp;quot;text-align: center&amp;quot;&lt;br /&gt;
| '''a''' || '''b''' || '''c''' || '''d''' || '''e'''&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tex&amp;gt; 0 &amp;lt;/tex&amp;gt; || &amp;lt;tex&amp;gt;\infty&amp;lt;/tex&amp;gt; || &amp;lt;tex&amp;gt;\infty&amp;lt;/tex&amp;gt; || &amp;lt;tex&amp;gt;\infty&amp;lt;/tex&amp;gt; || &amp;lt;tex&amp;gt;\infty&amp;lt;/tex&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
|style=&amp;quot;padding-left: 1em&amp;quot; | Извлечём из множества вершину '''a''', так как её приоритет минимален.&amp;lt;br/&amp;gt;Рассмотрим смежные с ней вершины '''b''', '''c''', и '''e'''. &amp;lt;br/&amp;gt;Обновим их приоритеты, как веса соответствующих рёбер '''ab''', '''ac''' и '''ae''', которые будут добавлены в ответ.&lt;br /&gt;
|-&lt;br /&gt;
|[[Файл:Mst_prima_2.png|200px]]&lt;br /&gt;
|&lt;br /&gt;
{| width=&amp;quot;100%&amp;quot; style = &amp;quot;text-align: center&amp;quot;&lt;br /&gt;
| a || '''b''' || '''c''' || '''d''' || '''e'''&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tex&amp;gt; 0 &amp;lt;/tex&amp;gt; || &amp;lt;tex&amp;gt; 3 &amp;lt;/tex&amp;gt; || &amp;lt;tex&amp;gt; 4 &amp;lt;/tex&amp;gt; || &amp;lt;tex&amp;gt;\infty&amp;lt;/tex&amp;gt; || &amp;lt;tex&amp;gt; 1 &amp;lt;/tex&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
|style=&amp;quot;padding-left: 1em&amp;quot; |Теперь минимальный приоритет у вершины '''е'''.&amp;lt;br/&amp;gt; Извлечём её и рассмотрим смежные с ней вершины '''a''', '''c''', и '''d'''.&amp;lt;br/&amp;gt;Изменим приоритет только у вершины '''d''', так как приоритеты вершин '''a''' и '''с''' меньше,&amp;lt;br/&amp;gt;чем веса у соответствующих рёбер '''ea''' и '''ec''', и установим приоритет вершины '''d''' равный весу ребра '''ed''', которое будет добавлено в ответ.&lt;br /&gt;
|-&lt;br /&gt;
|[[Файл:Mst_prima_3.png|200px]]&lt;br /&gt;
|&lt;br /&gt;
{| width=&amp;quot;100%&amp;quot; style = &amp;quot;text-align: center&amp;quot;&lt;br /&gt;
| a || '''b''' || '''c''' || '''d''' || e&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tex&amp;gt; 0 &amp;lt;/tex&amp;gt; || &amp;lt;tex&amp;gt; 3 &amp;lt;/tex&amp;gt; || &amp;lt;tex&amp;gt; 4 &amp;lt;/tex&amp;gt; || &amp;lt;tex&amp;gt; 7 &amp;lt;/tex&amp;gt; || &amp;lt;tex&amp;gt; 1 &amp;lt;/tex&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
|style=&amp;quot;padding-left: 1em&amp;quot; |После извлечения вершины '''b''' ничего не изменится, так как приоритеты вершин '''a''' и '''с''' меньше,&amp;lt;br/&amp;gt;чем веса у соответствующих рёбер '''ba''' и '''bc'''. Однако, после извлечения следующей вершины {{---}} '''c''',&amp;lt;br/&amp;gt;будет обновлён приоритет у вершины '''d''' на более низкий (равный весу ребра '''cd''') и в ответе ребро '''ed''' будет заменено на '''cd'''.&lt;br /&gt;
|-&lt;br /&gt;
|[[Файл:Mst_prima_4.png|200px]]&lt;br /&gt;
|&lt;br /&gt;
{| width=&amp;quot;100%&amp;quot; style = &amp;quot;text-align: center&amp;quot;&lt;br /&gt;
| a || b || c || '''d''' || e&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tex&amp;gt; 0 &amp;lt;/tex&amp;gt; || &amp;lt;tex&amp;gt; 3 &amp;lt;/tex&amp;gt; || &amp;lt;tex&amp;gt; 4 &amp;lt;/tex&amp;gt; || &amp;lt;tex&amp;gt; 2 &amp;lt;/tex&amp;gt; || &amp;lt;tex&amp;gt; 1 &amp;lt;/tex&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
|style=&amp;quot;padding-left: 1em&amp;quot; |Далее будет рассмотрена следующая вершина {{---}} '''d''', но ничего не изменится,&amp;lt;br/&amp;gt;так как приоритеты вершин '''e''' и '''с''' меньше, чем веса у соответствующих рёбер '''de''' и '''dc'''.&amp;lt;br/&amp;gt;После этого алгоритм завершит работу, так как в заданном множестве не останется вершин,&amp;lt;br/&amp;gt;которые не были бы рассмотрены&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Корректность ==&lt;br /&gt;
По поддерживаемым инвариантам после извлечения вершины &amp;lt;tex&amp;gt;v\ (v \neq r)&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;Q&amp;lt;/tex&amp;gt; ребро &amp;lt;tex&amp;gt;\left(v,p(v)\right)&amp;lt;/tex&amp;gt; является ребром минимального веса, пересекающим разрез &amp;lt;tex&amp;gt;\left(F,Q\right)&amp;lt;/tex&amp;gt;. Значит, по [[Лемма о безопасном ребре|лемме о безопасном ребре]], оно безопасно. Алгоритм построения ''MST'', добавляющий безопасные ребра, причём делающий это ровно &amp;lt;tex&amp;gt;|V|-1&amp;lt;/tex&amp;gt; раз, корректен.&lt;br /&gt;
&lt;br /&gt;
== Оценка производительности ==&lt;br /&gt;
Производительность алгоритма Прима зависит от выбранной реализации приоритетной очереди, как и в алгоритме Дейкстры. Извлечение минимума выполняется &amp;lt;tex&amp;gt;V&amp;lt;/tex&amp;gt; раз, релаксация — &amp;lt;tex&amp;gt;O(E)&amp;lt;/tex&amp;gt; раз.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;5&amp;quot; cellspacing=&amp;quot;0&amp;quot; style=&amp;quot;text-align:center&amp;quot; width=30%&lt;br /&gt;
!style=&amp;quot;background:#f2f2f2&amp;quot;|Структура данных для приоритетной очереди&lt;br /&gt;
!style=&amp;quot;background:#f2f2f2&amp;quot;|Асимптотика времени работы&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background:#f9f9f9&amp;quot;|Наивная реализация&lt;br /&gt;
|style=&amp;quot;background:#f9f9f9&amp;quot;|&amp;lt;tex&amp;gt;O(V^2+E)&amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background:#f9f9f9&amp;quot;|[[Двоичная куча]]&lt;br /&gt;
|style=&amp;quot;background:#f9f9f9&amp;quot;|&amp;lt;tex&amp;gt;O(E\log{V})&amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background:#f9f9f9&amp;quot;|[[Фибоначчиевы кучи|Фибоначчиева куча]]&lt;br /&gt;
|style=&amp;quot;background:#f9f9f9&amp;quot;|&amp;lt;tex&amp;gt;O(V\log{V}+E)&amp;lt;/tex&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[Алгоритм Краскала]]&lt;br /&gt;
* [[Алгоритм Борувки]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
*Томас Х. Кормен, Чарльз И. Лейзерсон, Рональд Л. Ривест, Клиффорд Штайн — Алгоритмы: построение и анализ, 2-е издание. Пер. с англ. — М.:Издательский дом &amp;quot;Вильямс&amp;quot;, 2010. — с.653 — 656.— ISBN 978-5-8459-0857-5 (рус.)&lt;br /&gt;
*[http://ru.wikipedia.org/wiki/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9F%D1%80%D0%B8%D0%BC%D0%B0 Википедия — Алгоритм Прима]&lt;br /&gt;
*[http://en.wikipedia.org/wiki/Prim%27s_algorithm Wikipedia — Prim's algorithm]&lt;br /&gt;
*[http://e-maxx.ru/algo/mst_prim MAXimal :: algo :: Минимальное остовное дерево. Алгоритм Прима]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Остовные деревья ]]&lt;/div&gt;</summary>
		<author><name>5.45.192.105</name></author>	</entry>

	</feed>