
Лекции - Структуры и алгоритмы компьютерной обработки данных / 18.Построение минимального остовного дерева (алгоритмы Прима и Крускала)
..docЗадача о минимальном остовном дереве
Остовое дерево (каркас) связного неориентированного графа – связный ациклический подграф. Минимальное остовное дерево (MST) – остовное дерево с минимальным суммарным весом ребер.
Задача о ремонте сети дорог.
Два алгоритма:
-
Краскала-Борувки
-
Прима-Дейкстры
Алгоритм Краскала-Борувки
-
Сортируем ребра в порядке возрастания весов
-
Добавляем ребра в дерево в отсортированном порядке, так чтобы не образовывались циклы
Пример: 1. Порядок ребер 1-3 6-7 1-2 2-4 3-4 1-5 5-6 7-8 2-6 5-8 4-7
2. Берем ребра 1-3 6-7 1-2 2-4
3-4 не берем (образует цикл 1-2-3-4)
Берем 1-5 5-6 7-8
Отслеживание циклов
Компоненты связности графа образуют непересекающиеся множества. Ребро образует цикл, если соединяет вершины, принадлежащие одному множеству.
Для работы с множествами используются различные структуры данных. Необходима поддержка операций
MakeSet(x) – создать множество
FindSet(x) – найти множество
Union(x,y) – объединить два множества
Простейший вариант – массив с номерами компонентов. Лучший вариант – лес корневых деревьев, с использованием объединения по рангу и сжатием путей (Кормен). Сложность одной операции – O(log n)
Схема процедуры алгоритма Краскала
Пусть E[1..m][1..2] – массив ребер
for i:=1 to n do MakeSet(i);
Sort(E);
for i:=1 to m do
if FindSet(E[i][1])<>FindSet(E[i][2]) then begin
Print(E[i]);
Union (E[i][1],E[i][2]);
end;
Сложность – Ө(m log m)
Алгоритм Прима-Дейкстры
Начинаем построение с произвольной вершины. Далее на каждом шаге добавляем в дерево вершину, ближайшую к вершинам дерева, ранее не добавленную.
Пример:
-
Начинаем с вершины 1.
-
Добавляем вершину 3. 1-3
-
Добавляем вершину 2 1-2
-
Добавляем вершину 4 2-4
-
Добавляем вершину 5 1-5
-
Добавляем вершину 6 5-6
-
Добавляем вершину 7 6-7
-
Добавляем вершину 8 7-8
Процедура алгоритма Прима
D[1..n] – массив расстояний; P[1..N] – номер ближайшего соседа из дерева; V[1..N] – массив пометок.
//инициализация
V[1]:=true; for i:=2 to n do V[i]:=false;
for i:=1 to n do D[i]:=A[1,i];
for i:=1 to n do P[i]:=1;
//основной цикл
for i:=2 to n do
begin //поиск ближайшей вершины
min:=oo;
for i:=1 to n do
if not(V[i]) and (D[i]< min)
then begin min:=D[i]; m:=i end;
V[m]:=true; //обновление расстояний
for i:=1 to n
if not(V[i]) and (D[i] > A[i,m])
then begin D[i]:=A[i,m]; P[i]:=m end;
end; //Сложность – O(n2)