
Алгоритмы на графах (на псевдокоде) / МОД&Кратч
.rtfМинимальное остовное дерево (МОД)
Алгоритм построения МОД ( Prim, Dijkstra ; O(n*n); "ближ.соседа" ) |
Алгоритм построения МОД сложности O(m*log n) |
Вход : V - множество вершин заданного графа G=(V,E) D [1..n,1..n] – матрица весов (или ф-ия D(.,.) ) Выход: Vt - множество вершин МОД, Et - множество ветвей МОД, Wt - общий вес МОД Рабочие: Near[1..(n-1)] - массив вершин, Near[v] – вершина дерева T=(Vt,Et), ближайшая к вершине v, еще не включенной в T begin {алгоритм МОД } {выбор произвольной вершины v0} Vt := {v0}; Et := { } ; Wt := 0; for v (V \ Vt) do Near[v] := v0; {инициализация Near[*] } while Card(Vt) < n do begin {ф1:} v := вершина из (V \ Vt) с минимальным значением D[v,Near[v]] ; {см. далее} Vt := Vt +{v}; Et := Et + { {v,Near[v]} } ; Wt := Wt + D [v,Near[v]]; {добавили v к дереву T} {коррекция массива Near[*] после включения v в T : } for x (V \ Vt) do if D [x,Near[x]] > D [x,v] then Near[x] := v; end{{while} end {алгоритма МОД }; {Детализация фрагмента ф1:} min := + ; for x (V \ Vt) do if D [x,Near[x]] < min then begin min := D [x,Near[x]] ; v := x end; {Можно наряду с Near[*] использовать рабочий массив расстояний Dist[x] = D [x,Near[x]] }
Жадный алгоритм построения МОД (Kruskal, O(m*log m))
Vs - множество множеств узлов поддеревьев остовного леса
Begin {алгоритм МОД } Vs := { }; T:= { }; For v V do добавить {v} к Vs; Построить очередь Q из всех ребер eE, упорядочив по возрастанию весов; While Card(Vs) > 1 do begin Выбрать из Q ребро e={u,v} с минимальным весом; Удалить e из Q; If u и v принадлежат разным подмножествам W1 и W2 из Vs then begin Заменить W1 и W2 на W1 W2 в Vs; T := T {e} end end{{while} end {алгоритма МОД }; Сложность алгоритма O(m*log m) при соответствующей реализации набора непересекающихся подмножеств Vs.
|
Вход : V - множество вершин заданного графа G=(V,E) E - множество ребер заданного графа G=(V,E) D [1..n,1..n] - матрица весов (или ф-ия D(.,.) ) Выход: T - множество ребер МОД Рабочие: C - множество связных компонент графа (V,T) - лес; C = {S1,...,Sk} Кратч[1..n] – массив ребер; Кратч[i] - ребро, кратчайшее из всех ребер, имеющих ровно один конец (вершину) в дереве (в связной компоненте) Si=(Vi,Ti); Min[1..n] - вспомогательный массив для определения Кратч[i]}
Begin T:={ }; C :={ {v1},...,{vn} }; While Card(C)<>1 do Begin for Si C do min[i]:=+; for {u,v} E do begin пусть i и j такие, что (u Si) & (v Sj); if i<>j then begin if d(u,v) < min[i] then begin min[i] := d(u,v); Кратч[i] :={u,v} end; if d(u,v) < min[j] then begin min[j] := d(u,v); Кратч[j] := u,v end end {if} end {for}; {здесь Кратч[i] – кратч. из всех ребер, имеющих ровно один конец в дереве Si=(Vi,Ti)} for Si C do T := T + { Кратч[i] } ; Найти множество C связных компонент графа (V,T) End {while} End
{Примечание: если при нахождении связных компонент вычислен массив NumComp[*], то i и j определяются так i := NumComp[u]; j := NumComp[v] } |
Кратчайшие пути в графе
1. Алгоритм нахождения кратчайшего пути по расстояниям между вершинами |
3. Алгоритм Дейкстры (Dijkstra E.W. - 1959) нахождения расстояний от источника до всех остальных вершин в графе с неотрицательными весами дуг
|
Дано:
Результат: St – стек, содержащий кратчайший путь от s до t, т.е. последовательность вершин s=v0, v1, … , vk=t Begin Create(st); st t; v:=t; While vs do Begin u:= вершина, для которой DL[v]=DL[u]+W[u,v]; St u; v:=u; End {while} End
2. Алгоритм Форда-Беллмана нахождения расстояний от источника до остальных вершин в графе , не содержащем контуров отрицательной длины
Дано:
(граф не содержит контуров отрицательной длины) Результат: Расстояния от источника s до всех вершин графа DL[v] = d(s,v), v V; Begin For v V do DL[v]:=W[s,v]; DL[s]:=0;
For k:=1 to n-2 do For v V \ {s} do For u V do DL[v] := min { DL[v], DL[u]+W[u,v] } End
Индуктивное утверждение (“инвариант”) цикла For k:=1 to n-2 do: P( [1..k) ) ( d(s,v) DL[v] d[ k | v ] ) - инвариант точки входа тела цикла, P( [1..k] ) ( d(s,v) DL[v] d[k+1| v ] ) - инвариант точки выхода тела цикла, где d[ k | v ] – длина кратчайшего из путей из s в v, содержащих не более k дуг.
|
Дано:
Результат: Расстояния от источника s до всех вершин графа DL[v]=d(s,v), v V; Begin For v V do DL[v]:=W[s,v]; DL[s]:=0; T:= V \ {s}; { S={s} } While T{ } do Begin u:= произвольная вершина xT, такая, что DL[x] = min { DL[p] : pT }; T:=T \ {u}; { S:=S+{u} } For v T do DL[v] := min { DL[v], DL[u]+W[u,v] } End {while} End Инвариант цикла while: ( V = T + S ) & ( T S = { } ) & ( vS : DL[v] = d(s,v) ) & ( vT : DL[v] = длина кратчайшего из тех путей из s в v, в которых все вершины, кроме v, принадлежат множеству S ) _____________________________________________________________________________ Модификация алгоритма Дейкстры (сложности O(m log n) )
с приоритетами DL[v]; при этом Inv Heap(T): (uT: (u=отец (v)) (DL[u] DL[v]) ). Тогда min(T) – в корне Heap(T), и исключение u из T есть удаление корня Heap(T) с восстановлением пирамидальности. 2) Используются списки смежности Adj[*]. Тогда обновление DL[v] после выбора вершины u реализуется следующим образом: _____________________________________________________________________________ For v Adj[u] do If DL[u]+W[u,v]<DL[v] then Begin DL[v] := DL[u]+W[u,v]; Восстановить пирамидальность Heap(T) вверх от узла v; End
|