Аналогия с алгоритмом Дейкстры

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

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

Такое поддерево называется минимальным остовным деревом или просто минимальным остовом. Легко понять, что любой остов обязательно будет содержать Аналогия с алгоритмом Дейкстры - student2.ru ребро.

В естественной постановке эта задача звучит следующим образом: есть Аналогия с алгоритмом Дейкстры - student2.ru городов, и для каждой пары известна стоимость соединения их дорогой (либо известно, что соединить их нельзя). Требуется соединить все города так, чтобы можно было доехать из любого города в другой, а при этом стоимость прокладки дорог была бы минимальной.

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

Этот алгоритм назван в честь американского математика Роберта Прима (Robert Prim), который открыл этот алгоритм в 1957 г. Впрочем, ещё в 1930 г. этот алгоритм был открыт чешским математиком Войтеком Ярником (Vojtěch Jarník). Кроме того, Эдгар Дейкстра (Edsger Dijkstra) в 1959 г. также изобрёл этот алгоритм, независимо от них.

Описание алгоритма

Сам алгоритм имеет очень простой вид. Искомый минимальный остов строится постепенно, добавлением в него рёбер по одному. Изначально остов полагается состоящим из единственной вершины (её можно выбрать произвольно). Затем выбирается ребро минимального веса, исходящее из этой вершины, и добавляется в минимальный остов. После этого остов содержит уже две вершины, и теперь ищется и добавляется ребро минимального веса, имеющее один конец в одной из двух выбранных вершин, а другой — наоборот, во всех остальных, кроме этих двух. И так далее, т.е. всякий раз ищется минимальное по весу ребро, один конец которого — уже взятая в остов вершина, а другой конец — ещё не взятая, и это ребро добавляется в остов (если таких рёбер несколько, можно взять любое). Этот процесс повторяется до тех пор, пока остов не станет содержать все вершины (или, что то же самое, Аналогия с алгоритмом Дейкстры - student2.ru ребро).

В итоге будет построен остов, являющийся минимальным. Если граф был изначально не связен, то остов найден не будет (количество выбранных рёбер останется меньше Аналогия с алгоритмом Дейкстры - student2.ru ).

Доказательство

Пусть граф Аналогия с алгоритмом Дейкстры - student2.ru был связным, т.е. ответ существует. Обозначим через Аналогия с алгоритмом Дейкстры - student2.ru остов, найденный алгоритмом Прима, а через Аналогия с алгоритмом Дейкстры - student2.ru — минимальный остов. Очевидно, что Аналогия с алгоритмом Дейкстры - student2.ru действительно является остовом (т.е. поддеревом графа Аналогия с алгоритмом Дейкстры - student2.ru ). Покажем, что веса Аналогия с алгоритмом Дейкстры - student2.ru и Аналогия с алгоритмом Дейкстры - student2.ru совпадают.

Рассмотрим первый момент времени, когда в Аналогия с алгоритмом Дейкстры - student2.ru происходило добавление ребра, не входящего в оптимальный остов Аналогия с алгоритмом Дейкстры - student2.ru . Обозначим это ребро через Аналогия с алгоритмом Дейкстры - student2.ru , концы его — через Аналогия с алгоритмом Дейкстры - student2.ru и Аналогия с алгоритмом Дейкстры - student2.ru , а множество входящих на тот момент в остов вершин — через Аналогия с алгоритмом Дейкстры - student2.ru (согласно алгоритму, Аналогия с алгоритмом Дейкстры - student2.ru , Аналогия с алгоритмом Дейкстры - student2.ru , либо наоборот). В оптимальном остове Аналогия с алгоритмом Дейкстры - student2.ru вершины Аналогия с алгоритмом Дейкстры - student2.ru и Аналогия с алгоритмом Дейкстры - student2.ru соединяются каким-то путём Аналогия с алгоритмом Дейкстры - student2.ru ; найдём в этом пути любое ребро Аналогия с алгоритмом Дейкстры - student2.ru , один конец которого лежит в Аналогия с алгоритмом Дейкстры - student2.ru , а другой — нет. Поскольку алгоритм Прима выбрал ребро Аналогия с алгоритмом Дейкстры - student2.ru вместо ребра Аналогия с алгоритмом Дейкстры - student2.ru , то это значит, что вес ребра Аналогия с алгоритмом Дейкстры - student2.ru больше либо равен весу ребра Аналогия с алгоритмом Дейкстры - student2.ru .

Удалим теперь из Аналогия с алгоритмом Дейкстры - student2.ru ребро Аналогия с алгоритмом Дейкстры - student2.ru , и добавим ребро Аналогия с алгоритмом Дейкстры - student2.ru . По только что сказанному, вес остова в результате не мог увеличиться (уменьшиться он тоже не мог, поскольку Аналогия с алгоритмом Дейкстры - student2.ru было оптимальным). Кроме того, Аналогия с алгоритмом Дейкстры - student2.ru не перестало быть остовом (в том, что связность не нарушилась, нетрудно убедиться: мы замкнули путь Аналогия с алгоритмом Дейкстры - student2.ru в цикл, и потом удалили из этого цикла одно ребро).

Итак, мы показали, что можно выбрать оптимальный остов Аналогия с алгоритмом Дейкстры - student2.ru таким образом, что он будет включать ребро Аналогия с алгоритмом Дейкстры - student2.ru . Повторяя эту процедуру необходимое число раз, мы получаем, что можно выбрать оптимальный остов Аналогия с алгоритмом Дейкстры - student2.ru так, чтобы он совпадал с Аналогия с алгоритмом Дейкстры - student2.ru . Следовательно, вес построенного алгоритмом Прима Аналогия с алгоритмом Дейкстры - student2.ru минимален, что и требовалось доказать.

Реализации

Время работы алгоритма существенно зависит от того, каким образом мы производим поиск очередного минимального ребра среди подходящих рёбер. Здесь могут быть разные подходы, приводящие к разным асимптотикам и разным реализациям.

Тривиальная реализация: алгоритмы за Аналогия с алгоритмом Дейкстры - student2.ru и Аналогия с алгоритмом Дейкстры - student2.ru

Если искать каждый раз ребро простым просмотром среди всех возможных вариантов, то асимптотически будет требоваться просмотр Аналогия с алгоритмом Дейкстры - student2.ru рёбер, чтобы найти среди всех допустимых ребро с наименьшим весом. Суммарная асимптотика алгоритма составит в таком случае Аналогия с алгоритмом Дейкстры - student2.ru , что в худшем случае есть Аналогия с алгоритмом Дейкстры - student2.ru , — слишком медленный алгоритм.

Этот алгоритм можно улучшить, если просматривать каждый раз не все рёбра, а только по одному ребру из каждой уже выбранной вершины. Для этого, например, можно отсортировать рёбра из каждой вершины в порядке возрастания весов, и хранить указатель на первое допустимое ребро (напомним, допустимы только те рёбра, которые ведут в множество ещё не выбранных вершин). Тогда, если пересчитывать эти указатели при каждом добавлении ребра в остов, суммарная асимптотика алгоритма будет Аналогия с алгоритмом Дейкстры - student2.ru , но предварительно потребуется выполнить сортировку всех рёбер за Аналогия с алгоритмом Дейкстры - student2.ru , что в худшем случае (для плотных графов) даёт асимптотику Аналогия с алгоритмом Дейкстры - student2.ru .

Ниже мы рассмотрим два немного других алгоритма: для плотных и для разреженных графов, получив в итоге заметно лучшую асимптотику.

Случай плотных графов: алгоритм за Аналогия с алгоритмом Дейкстры - student2.ru

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

Тогда, чтобы на текущем шаге произвести выбор минимального ребра, надо просто просмотреть эти минимальные рёбра у каждой не выбранной ещё вершины — асимптотика составит Аналогия с алгоритмом Дейкстры - student2.ru .

Но теперь при добавлении в остов очередного ребра и вершины эти указатели надо пересчитывать. Заметим, что эти указатели могут только уменьшаться, т.е. у каждой не просмотренной ещё вершины надо либо оставить её указатель без изменения, либо присвоить ему вес ребра в только что добавленную вершину. Следовательно, эту фазу можно сделать также за Аналогия с алгоритмом Дейкстры - student2.ru .

Таким образом, мы получили вариант алгоритма Прима с асимптотикой Аналогия с алгоритмом Дейкстры - student2.ru .

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

Реализация алгоритма Прима для графа, заданного матрицей смежности Аналогия с алгоритмом Дейкстры - student2.ru :

// входные данныеint n;vector < vector<int> > g;const int INF = 1000000000; // значение "бесконечность" // алгоритмvector<bool> used (n);vector<int> min_e (n, INF), sel_e (n, -1);min_e[0] = 0;for (int i=0; i<n; ++i) { int v = -1; for (int j=0; j<n; ++j) if (!used[j] && (v == -1 || min_e[j] < min_e[v])) v = j; if (min_e[v] == INF) { cout << "No MST!"; exit(0); } used[v] = true; if (sel_e[v] != -1) cout << v << " " << sel_e[v] << endl; for (int to=0; to<n; ++to) if (g[v][to] < min_e[to]) { min_e[to] = g[v][to]; sel_e[to] = v; }}

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

Случай разреженных графов: алгоритм за Аналогия с алгоритмом Дейкстры - student2.ru

В описанном выше алгоритме можно увидеть стандартные операции нахождения минимума в множестве и изменение значений в этом множестве. Эти две операции являются классическими, и выполняются многими структурами данных, например, реализованным в языке C++ красно-чёрным деревом set.

По смыслу алгоритм остаётся точно таким же, однако теперь мы можем найти минимальное ребро за время Аналогия с алгоритмом Дейкстры - student2.ru . С другой стороны, время на пересчёт Аналогия с алгоритмом Дейкстры - student2.ru указателей теперь составит Аналогия с алгоритмом Дейкстры - student2.ru , что хуже, чем в вышеописанном алгоритме.

Если учесть, что всего будет Аналогия с алгоритмом Дейкстры - student2.ru пересчётов указателей и Аналогия с алгоритмом Дейкстры - student2.ru поисков минимального ребра, то суммарная асимптотика составит Аналогия с алгоритмом Дейкстры - student2.ru — для разреженных графов это лучше, чем оба вышеописанных алгоритма, но на плотных графах этот алгоритм будет медленнее предыдущего.

Реализация алгоритма Прима для графа, заданного списками смежности Аналогия с алгоритмом Дейкстры - student2.ru :

// входные данныеint n;vector < vector < pair<int,int> > > g;const int INF = 1000000000; // значение "бесконечность" // алгоритмvector<int> min_e (n, INF), sel_e (n, -1);min_e[0] = 0;set < pair<int,int> > q;q.insert (make_pair (0, 0));for (int i=0; i<n; ++i) { if (q.empty()) { cout << "No MST!"; exit(0); } int v = q.begin()->second; q.erase (q.begin()); if (sel_e[v] != -1) cout << v << " " << sel_e[v] << endl; for (size_t j=0; j<g[v].size(); ++j) { int to = g[v][j].first, cost = g[v][j].second; if (cost < min_e[to]) { q.erase (make_pair (min_e[to], to)); min_e[to] = cost; sel_e[to] = v; q.insert (make_pair (min_e[to], to)); } }}

На вход подаются число вершин Аналогия с алгоритмом Дейкстры - student2.ru и Аналогия с алгоритмом Дейкстры - student2.ru списков смежности: Аналогия с алгоритмом Дейкстры - student2.ru — это список всех рёбер, исходящих из вершины Аналогия с алгоритмом Дейкстры - student2.ru , в виде пар (второй конец ребра, вес ребра). Алгоритм поддерживает два массива: величина Аналогия с алгоритмом Дейкстры - student2.ru хранит вес наименьшего допустимого ребра из вершины Аналогия с алгоритмом Дейкстры - student2.ru , а элемент Аналогия с алгоритмом Дейкстры - student2.ru содержит конец этого наименьшего ребра (это нужно для вывода рёбер в ответе). Кроме того, поддерживается очередь Аналогия с алгоритмом Дейкстры - student2.ru из всех вершин в порядке увеличения их меток Аналогия с алгоритмом Дейкстры - student2.ru . Алгоритм делает Аналогия с алгоритмом Дейкстры - student2.ru шагов, на каждом из которых выбирает вершину Аналогия с алгоритмом Дейкстры - student2.ru с наименьшей меткой Аналогия с алгоритмом Дейкстры - student2.ru (просто извлекая её из начала очереди), и затем просматривает все рёбра из этой вершины, пересчитывая их метки (при пересчёте мы удаляем из очереди старую величину, и затем кладём обратно новую).

Аналогия с алгоритмом Дейкстры

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

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

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

Наши рекомендации