Алгоритм Краскала

Материал из Викиконспекты
Версия от 22:10, 15 декабря 2014; 188.227.78.184 (обсуждение) (Задача о максимальном ребре минимального веса)
Перейти к: навигация, поиск

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

Идея

Будем последовательно строить подграф [math]F[/math] графа [math]G[/math] ("растущий лес"), пытаясь на каждом шаге достроить [math]F[/math] до некоторого MST. Начнем с того, что включим в [math]F[/math] все вершины графа [math]G[/math]. Теперь будем обходить множество [math]E(G)[/math] в порядке неубывания веса ребер. Если очередное ребро [math]e[/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]e[/math] является безопасным, поэтому добавим это ребро в [math]F[/math]. На последнем шаге ребро соединит две оставшиеся компоненты связности, полученный подграф будет минимальным остовным деревом графа [math]G[/math].

Реализация

// [math]G[/math] — исходный граф
// [math]F[/math] — минимальный остов
// для проверки возможности добавления ребра используется система непересекающихся множеств
function [math]\mathtt{kruskalFindMST}():[/math]
   [math] \mathtt{F} \leftarrow V(G)[/math]
   [math]\mathtt{sort}(E(G))\[/math]
   for [math]vu \in E(G)[/math]
      if [math]v[/math] и [math]u[/math] в разных компонентах связности [math]F[/math]
         [math] \mathtt{F}\ =\ \mathtt{F} \bigcup \mathtt{vu}\[/math]

Задача о максимальном ребре минимального веса

Очевидно, что максимальное ребро в MST минимально. Пусть это не так, тогда рассмотрим разрез, который оно пересекает. В этом разрезе должно быть ребро с меньшим весом, иначе максимальное ребро было бы минимальным, но в таком случае минимальный остов не является минимальным, следовательно, максимальное ребро в минимальном остовном дереве минимально. Если же максимальное ребро в остовном дереве минимально, то такое дерево может не быть минимальным. Зато его можно найти быстрее чем MST, а конкретно за [math]O(E)[/math]. Описанный далее алгоритм ищет максимальное ребро минимального веса, точнее ребро максимального веса минимального остовного дерева. С помощью алгоритма поиска k-ой порядковой статистики найдем ребро-медиану за [math]O(E)[/math] и разделим множество ребер на два равных по мощности так, чтобы в первом подмножестве все ребра не превосходили ребро-медиану, а во втором были не меньше его. Запустим обход в глубину, чтобы проверить образуют ли ребра из первого подмножества остов, содержащий все вершины графа. Если да, то самые легкие и все безопасные ребра находятся в первом подмножестве, поэтому рекурсивно запустим алгоритм от него, а второе подмножество ребер "выкинем". В противном случае часть безопасных ребер, включая ребро, которое мы ищем, находится во втором подмножестве, поэтому сконденсируем в супервершины получившиеся несвязные компоненты и рассмотрим граф с этими вершинами и ребрами из второго подмножества. В сконденсированных компонентах могут быть небезопасные ребра, но это не имеет значения, так как вес всех ребер первого подмножества меньше веса ребра, которого мы ищем, следовательно, они не повлияют на ответ. На последнем шаге останутся всего две компоненты связности, а в первом подмножестве будет содержаться лишь одно ребро, это ребро и будет максимальным ребром минимального веса или максимальным ребром минимального остова, так как оно наименьшее по весу среди всех ребер, пересекающих [math] \langle S, T \rangle [/math] разрез между данными компонентами. На каждом шаге ребер становится в два раза меньше, а все операции выполняются за время пропорциональное количеству ребер на текущем шаге, следовательно, время работы алгоритма [math]O(E+\frac{E}{2}+\frac{E}{4}+...+1)=O(E)[/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].
Работа с системой непересекающихся множеств займет [math]O(E\alpha(V))[/math], где [math]\alpha[/math] — обратная функция Аккермана, которая не превосходит 4 во всех практических приложениях и которую можно принять за константу.
Алгоритм работает за [math]O(E(\log E+\alpha(V))) = O(E\log E)[/math].

См. также

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