Алгоритм Краскала — различия между версиями

Материал из Викиконспекты
Перейти к: навигация, поиск
(Пример)
(Реализация)
Строка 6: Строка 6:
  
 
==Реализация==
 
==Реализация==
<b>Вход</b>: граф <tex>G = (V, E)</tex><br>
+
<font color=green>// <tex>G</tex> {{---}} исходный граф</font>
<b>Выход</b>: минимальный остов <tex>F</tex> графа <tex>G</tex><br>
+
<font color=green>// <tex>F</tex> {{---}} минимальный остов</font>
1) <tex>F := (V, \varnothing)</tex><br>
+
'''function''' <tex>\mathtt{kruskalFindMST}():</tex>
1) Отсортируем <tex>E</tex> по весу ребер.<br>
+
    <tex> \mathtt{F}\ =\ \varnothing </tex>
2) Заведем систему непересекающихся множеств (DSU) и инициализируем ее множеством <tex>V</tex>.<br>
+
    '''for''' <tex>v \in V(G)</tex>
3) Перебирая ребра <tex>uv \in EG</tex> в порядке увеличения веса, смотрим, принадлежат ли <tex>u</tex> и <tex>v</tex> одному множеству. Если нет, то объединяем множества, в которых лежат <tex>u</tex> и <tex>v</tex>, и добавляем ребро <tex>uv</tex> к <tex>F</tex>.<br>
+
      <tex>\mathtt{makeSet}(v)\</tex>
 +
    <tex>\mathtt{sort}(E(G))\</tex>
 +
    '''for''' <tex>vu \in E(G)</tex> в отсортированном порядке
 +
      '''if''' <tex>\mathtt{findSet}(u)\ \ne \mathtt{findSet}(v)</tex>
 +
          <tex> \mathtt{F}\ =\ \mathtt{F}\ \bigcup \mathtt{vu}\</tex>
 +
          <tex>\mathtt{Union}(v, u)\ </tex>
  
 
==Пример==
 
==Пример==

Версия 23:25, 3 ноября 2014

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

Идея

Будем последовательно строить подграф [math]F[/math] графа [math]G[/math] ("растущий лес"), поддерживая следующий инвариант: на каждом шаге [math]F[/math] можно достроить до некоторого MST. Начнем с того, что включим в [math]F[/math] все вершины графа [math]G[/math]. Теперь будем обходить множество [math]EG[/math] в порядке увеличения веса ребер. Добавление очередного ребра [math]e[/math] в [math]F[/math] может привести к возникновению цикла в одной из компонент связности [math]F[/math]. В этом случае, очевидно, [math]e[/math] не может быть включено в [math]F[/math]. В противном случае [math]e[/math] соединяет разные компоненты связности [math]F[/math], тогда существует разрез [math] \langle S, T \rangle [/math] такой, что одна из компонент связности составляет одну его часть, а оставшаяся часть графа - вторую. Тогда [math]e[/math] и есть минимальное ребро, пересекающее этот разрез. Значит, из леммы о безопасном ребре следует, что [math]F+e[/math] можно продолжить до MST, поэтому добавим это ребро в [math]F[/math].
Несложно понять, что после выполнения такой процедуры получится остовное дерево, при этом его минимальность вытекает из леммы о безопасном ребре.

Реализация

// [math]G[/math] — исходный граф
// [math]F[/math] — минимальный остов
function [math]\mathtt{kruskalFindMST}():[/math]
   [math] \mathtt{F}\ =\ \varnothing [/math]
   for [math]v \in V(G)[/math]
      [math]\mathtt{makeSet}(v)\[/math]
   [math]\mathtt{sort}(E(G))\[/math]
   for [math]vu \in E(G)[/math] в отсортированном порядке
      if [math]\mathtt{findSet}(u)\ \ne \mathtt{findSet}(v)[/math]
         [math] \mathtt{F}\ =\ \mathtt{F}\ \bigcup \mathtt{vu}\[/math]
         [math]\mathtt{Union}(v, u)\ [/math]

Пример

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

Рёбра (в порядке их просмотра) ae cd ab be bc ec ed
Веса рёбер [math]1[/math] [math]2[/math] [math]3[/math] [math]4[/math] [math]5[/math] [math]6[/math] [math]7[/math]
Изображение Описание
Mst kruskal 1.png Первое ребро, которое будет рассмотрено — ae, так как его вес минимальный.

Добавим его к ответу, так как его концы соединяют вершины из разных множеств (a — красное и e — зелёное).
Объединим красное и зелёное множество в одно (красное), так как теперь они соединены ребром.

Mst kruskal 2.png Рассмотрим следующие ребро — cd.

Добавим его к ответу, так как его концы соединяют вершины из разных множеств (c — синее и d — голубое).
Объединим синее и голубое множество в одно (синее), так как теперь они соединены ребром.

Mst kruskal 3.png Дальше рассмотрим ребро ab.

Добавим его к ответу, так как его концы соединяют вершины из разных множеств (a — красное и b — розовое).
Объединим красное и розовое множество в одно (красное), так как теперь они соединены ребром.

Mst kruskal 4.png Рассмотрим следующие ребро — be.

Оно соединяет вершины из одного множества, поэтому перейдём к следующему ребру bc
Добавим его к ответу, так как его концы соединяют вершины из разных множеств (b — красное и c — синее).
Объединим красное и синее множество в одно (красное), так как теперь они соединены ребром.

Mst kruskal 5.png Рёбра ec и ed соединяют вершины из одного множества,

поэтому после их просмотра они не будут добавлены в ответ
Всё рёбра были рассмотрены, поэтому алгоритм завершает работу.
Полученный граф — минимальное остовное дерево

Асимптотика

Сортировка [math]E[/math] займет [math]O(E\log E)[/math].
Работа с DSU займет [math]O(E\alpha(V))[/math], где [math]\alpha[/math] - обратная функция Аккермана, которая не превосходит 4 во всех практических приложениях и которую можно принять за константу.
Алгоритм работает за [math]O(E(\log E+\alpha(V))) = O(E\log E) = O(E\log V^2) = O(E\log V)[/math].

См. также

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