Редактирование: Алгоритм Краскала

Перейти к: навигация, поиск

Внимание! Вы не авторизовались на сайте. Ваш IP-адрес будет публично видимым, если вы будете вносить любые правки. Если вы войдёте или создадите учётную запись, правки вместо этого будут связаны с вашим именем пользователя, а также у вас появятся другие преимущества.

Правка может быть отменена. Пожалуйста, просмотрите сравнение версий, чтобы убедиться, что это именно те изменения, которые вас интересуют, и нажмите «Записать страницу», чтобы изменения вступили в силу.
Текущая версия Ваш текст
Строка 3: Строка 3:
 
==Идея==
 
==Идея==
 
Будем последовательно строить подграф <tex>F</tex> графа <tex>G</tex> ("растущий лес"), пытаясь на каждом шаге достроить <tex>F</tex> до некоторого MST. Начнем с того, что включим в <tex>F</tex> все вершины графа <tex>G</tex>. Теперь будем обходить множество <tex>E(G)</tex> в порядке неубывания весов ребер. Если очередное ребро <tex>e</tex> соединяет вершины одной компоненты связности <tex>F</tex>, то добавление его в остов приведет к возникновению цикла в этой компоненте связности. В таком случае, очевидно, <tex>e</tex> не может быть включено в <tex>F</tex>. Иначе <tex>e</tex> соединяет разные компоненты связности <tex>F</tex>, тогда существует <tex> \langle S, T \rangle </tex> [[Лемма о безопасном ребре#Необходимые определения|разрез]] такой, что одна из компонент связности составляет одну его часть, а оставшаяся часть графа — вторую. Тогда <tex>e</tex> — минимальное ребро, пересекающее этот разрез. Значит, из [[Лемма о безопасном ребре#Лемма о безопасном ребре|леммы о безопасном ребре]] следует, что <tex>e</tex> является безопасным, поэтому добавим это ребро в <tex>F</tex>. На последнем шаге ребро соединит две оставшиеся компоненты связности, полученный подграф будет минимальным остовным деревом графа <tex>G</tex>.
 
Будем последовательно строить подграф <tex>F</tex> графа <tex>G</tex> ("растущий лес"), пытаясь на каждом шаге достроить <tex>F</tex> до некоторого MST. Начнем с того, что включим в <tex>F</tex> все вершины графа <tex>G</tex>. Теперь будем обходить множество <tex>E(G)</tex> в порядке неубывания весов ребер. Если очередное ребро <tex>e</tex> соединяет вершины одной компоненты связности <tex>F</tex>, то добавление его в остов приведет к возникновению цикла в этой компоненте связности. В таком случае, очевидно, <tex>e</tex> не может быть включено в <tex>F</tex>. Иначе <tex>e</tex> соединяет разные компоненты связности <tex>F</tex>, тогда существует <tex> \langle S, T \rangle </tex> [[Лемма о безопасном ребре#Необходимые определения|разрез]] такой, что одна из компонент связности составляет одну его часть, а оставшаяся часть графа — вторую. Тогда <tex>e</tex> — минимальное ребро, пересекающее этот разрез. Значит, из [[Лемма о безопасном ребре#Лемма о безопасном ребре|леммы о безопасном ребре]] следует, что <tex>e</tex> является безопасным, поэтому добавим это ребро в <tex>F</tex>. На последнем шаге ребро соединит две оставшиеся компоненты связности, полученный подграф будет минимальным остовным деревом графа <tex>G</tex>.
Для проверки возможности добавления ребра используется  [[СНМ (реализация с помощью леса корневых деревьев) | система непересекающихся множеств]].
 
  
 
==Реализация==
 
==Реализация==
 
  <font color=green>// <tex>G</tex> {{---}} исходный граф</font>
 
  <font color=green>// <tex>G</tex> {{---}} исходный граф</font>
 
  <font color=green>// <tex>F</tex> {{---}} минимальный остов</font>
 
  <font color=green>// <tex>F</tex> {{---}} минимальный остов</font>
 +
<font color=green>// для проверки возможности добавления ребра используется система непересекающихся множеств</font>
 
  '''function''' <tex>\mathtt{kruskalFindMST}():</tex>
 
  '''function''' <tex>\mathtt{kruskalFindMST}():</tex>
 
     <tex> \mathtt{F} \leftarrow V(G)</tex>
 
     <tex> \mathtt{F} \leftarrow V(G)</tex>
Строка 17: Строка 17:
  
 
==Задача о максимальном ребре минимального веса==
 
==Задача о максимальном ребре минимального веса==
Легко показать, что максимальное ребро в MST минимально. Обратное в общем случае неверно. Но MST из-за сортировки строится за <tex>O(E \log E)</tex>. Однако из-за того, что необходимо минимизировать только максимальное ребро, а не сумму всех рёбер, можно предъявить алгоритм, решающий задачу за линейное время.
+
Очевидно, что максимальное ребро в MST минимально. Пусть это не так, тогда рассмотрим разрез, который оно пересекает. В этом разрезе должно быть ребро с меньшим весом, иначе максимальное ребро было бы минимальным, но в таком случае минимальный остов не является минимальным, следовательно, максимальное ребро в минимальном остовном дереве минимально. Если же максимальное ребро в остовном дереве минимально, то такое дерево может не быть минимальным. Зато его можно найти быстрее чем MST, а конкретно за <tex>O(E)</tex>. Описанный далее алгоритм ищет максимальное ребро минимального веса, которое также является ребром максимального веса минимального остовного дерева. С помощью [[Поиск_k-ой_порядковой_статистики_за_линейное_время | алгоритма поиска k-ой порядковой статистики]] найдем ребро-медиану за <tex>O(E)</tex> и разделим множество ребер на два равных по мощности так, чтобы в первом подмножестве все ребра не превосходили ребро-медиану, а во втором были не меньше его. Запустим [[Использование_обхода_в_глубину_для_проверки_связности|обход в глубину]], чтобы проверить образуют ли ребра из первого подмножества остов, содержащий все вершины графа. Если да, то самые легкие и все безопасные ребра находятся в первом подмножестве, поэтому рекурсивно запустим алгоритм от него, а второе подмножество ребер "выкинем". В противном случае часть безопасных ребер, включая ребро, которое мы ищем, находится во втором подмножестве, поэтому сконденсируем в супервершины получившиеся несвязные компоненты и рассмотрим граф с этими вершинами и ребрами из второго подмножества. В сконденсированных компонентах могут быть небезопасные ребра, но это не имеет значения, так как вес всех ребер первого подмножества меньше веса ребра, которого мы ищем, следовательно, они не повлияют на ответ. На последнем шаге останутся всего две компоненты связности, а в первом подмножестве будет содержаться лишь одно ребро, это ребро и будет максимальным ребром минимального веса или максимальным ребром минимального остова, так как оно наименьшее по весу среди всех ребер, пересекающих <tex> \langle S, T \rangle </tex> разрез между данными компонентами. На каждом шаге ребер становится в два раза меньше, а все операции выполняются за время пропорциональное количеству ребер на текущем шаге, тогда время работы алгоритма <tex>O(E+\frac{E}{2}+\frac{E}{4}+...+1)=O(E)</tex>. Чтобы восстановить остовное дерево, достаточно запустить алгоритм поиска в глубину и добавлять в остов только те ребра, которые не превосходят найденное алгоритмом ребро.
 
 
С помощью [[Поиск_k-ой_порядковой_статистики_за_линейное_время | алгоритма поиска k-ой порядковой статистики]] найдем ребро-медиану за <tex>O(E)</tex> и разделим множество ребер на два равных по мощности так, чтобы ребра в первом не превосходили по весу ребер во втором. Проверим образуют ли ребра из первого подмножества остов графа, запустив [[Использование_обхода_в_глубину_для_проверки_связности|обход в глубину]].  
 
* Если да, то рекурсивно запустим алгоритм от него.
 
* В противном случае сконденсируем получившиеся несвязные компоненты в супервершины и рассмотрим граф с этими вершинами и ребрами из второго подмножества.
 
На последнем шаге останутся две компоненты связности и одно ребро в первом подмножестве это максимальное ребро минимального веса.
 
 
 
На каждом шаге ребер становится в два раза меньше, а все операции выполняются за время пропорциональное количеству ребер на текущем шаге, тогда время работы алгоритма <tex>O(E+\frac{E}{2}+\frac{E}{4}+...+1)=O(E)</tex>.
 
  
 
==Пример==
 
==Пример==
Строка 66: Строка 59:
 
==Асимптотика==
 
==Асимптотика==
 
Сортировка <tex>E</tex> займет <tex>O(E\log E)</tex>.<br>
 
Сортировка <tex>E</tex> займет <tex>O(E\log E)</tex>.<br>
Работа с СНМ займет <tex>O(E\alpha(V))</tex>, где <tex>\alpha</tex> — обратная функция Аккермана, которая не превосходит <tex>4</tex> во всех практических приложениях и которую можно принять за константу.<br>
+
Для проверки возможности добавления ребра используется [[СНМ (реализация с помощью леса корневых деревьев) | система непересекающихся множеств]], работа с ней займет <tex>O(E\alpha(V))</tex>, где <tex>\alpha</tex> — обратная функция Аккермана, которая не превосходит <tex>4</tex> во всех практических приложениях и которую можно принять за константу.<br>
 
Алгоритм работает за <tex>O(E(\log E+\alpha(V))) = O(E\log E)</tex>.
 
Алгоритм работает за <tex>O(E(\log E+\alpha(V))) = O(E\log E)</tex>.
  
Строка 81: Строка 74:
  
 
[[Категория: Алгоритмы и структуры данных]]
 
[[Категория: Алгоритмы и структуры данных]]
[[Категория: Остовные деревья]]
+
[[Категория: Остовные деревья ]]
[[Категория: Построение остовных деревьев]]
 

Пожалуйста, учтите, что любой ваш вклад в проект «Викиконспекты» может быть отредактирован или удалён другими участниками. Если вы не хотите, чтобы кто-либо изменял ваши тексты, не помещайте их сюда.
Вы также подтверждаете, что являетесь автором вносимых дополнений, или скопировали их из источника, допускающего свободное распространение и изменение своего содержимого (см. Викиконспекты:Авторские права). НЕ РАЗМЕЩАЙТЕ БЕЗ РАЗРЕШЕНИЯ ОХРАНЯЕМЫЕ АВТОРСКИМ ПРАВОМ МАТЕРИАЛЫ!

Чтобы изменить эту страницу, пожалуйста, ответьте на приведённый ниже вопрос (подробнее):

Отменить | Справка по редактированию (в новом окне)

Шаблон, используемый на этой странице: