Кратчайшие пути для всех пар вершин взвешенного ориентированного графа, страница 2


Для k ³1:  t(k)ij =  t(k-1)ij Ú ( t(k-1)ik Ù t(k-1)kj)


Пример:


Алгоритм транзитивного замыкания последовательно вычисляет матрицы T(k) =(t(k)ij) для            k = 1,2,...,n.

Transitive_Closure(G)

1.  n←V[G]|

2.  for i←1 to n

3.        do for i←1 to n

4.                 do if  i=j или (i, j)ÎE[G]

5.                          then t(0)ij ←1

6.                          else =t(0)ij←0

7.  for k←1 to n

8.       do for i←1 to n

9.               do for j←1 to n

10.                       do t(k)ij ← t(k-1)ij  Ú ( t(k-1)ik  Ù  t(k-1)kj)

11.  return T(n)     

Алгоритм Джонсона нахождения всех пар кратчайших путей.

Этот алгоритм работает эффективнее, чем алгоритм Флойда - Уоршолла для разреженных графов. Его время O(V2 log V + VE). Алгоритм либо формирует матрицу кратчайших путей, либо сообщает, что в графе имеется цикл отрицательного веса. Работа алгоритма основана на использовании алгоритмов Беллмана - Форда и Дейкстры.

Особенностью алгоритма является изменения весов ребер графа, т. о. чтобы они были неотрицательны, и можно было бы применить алгоритм Дейкстры к каждой вершине.

При изменении весов ребер должны быть соблюдены следующие условия:

1)  Кратчайшие пути  в графе не изменяются, т. е. для любой пары вершин u, v ÏV кратчайший путь с точки зрения исходной весовой функции w совпадает  с кратчайшим путем с точки зрения новой весовой функции ~w.

2)  Все новые веса ~w(u, v) неотрицательны.

Необходимо подобрать способ изменения весов ребер  с соблюдением этих условий.

Пусть дан граф G=(V, E)  с весовой функцией w: EàR. Введем весовую функцию для вершин графа h: VàR.

Рассмотрим новую весовую функцию ~w: EàR, такую, что ~w(u, v)= w(u, v) + h(u) - h(v). Тогда любой кратчайший путь p = (v0, v1,..., vk) относительно w будет совпадать с кратчайшим путем относительно ~w.

Вес любого пути v0                vk относительно ~w(p) равен:  

~w(p)= w(p) + h(v0) - h(vk).

Т. е. для всех путей с фиксированным началом и концом разница между старым и новым весом постоянна и поэтому кратчайшие пути для новой и старой весовой функции совпадают.

~w(p)= w(v0, v1,) + h(v0) - h(v1) + w(v1, v2,) + h(v1) - h(v2) +... +w(vk-1, vk,) + h(vk-1) - h(vk) =

= w(v0, vk,) + h(v0) - h(vk)

Второе следствие при таком преобразовании:

Если граф G содержит отрицательный цикл относительно весовой функции w, то он содержит этот же отрицательный цикл относительно функции ~w. Это следствие исходит из того, что вес цикла равен:

~w(p)= w(p) + h(v0) - h(v0).

Чтобы перейти  к новой весовой функции с неотрицательными весами нужно подобрать весовую функцию h: VàR.


Для орграфа G=(V, E) построим эквивалентный орграф G`=(V`, E`) с дополнительной вершиной S, которая имеет только исходящие дуги нулевого веса ко всем остальным вершинам.

Введение этой вершины не изменит путей в новом графе, поскольку вершина S, не может быть вставлена в качестве промежуточной в пути, т. к. не имеет входящих ребер. Она может быть только начальной вершиной пути. Новый граф содержит цикл отрицательного веса, если таковой содержится в исходном графе.

Пусть граф G`, как и граф G не содержит цикла отрицательного веса. Пусть вес каждой вершины равен весу кратчайшего пути до этой вершины S, т. е. h(v) = d(S, v) для " vÎV`.

Для вершин, лежащих на кратчайшем пути выполняется свойство: h(v)£h(u)+w(u, v).  Поэтому w(u, v) + h(u) - h(v) ³ 0, т. е. новая весовая функция ~w(u, v) = w(u, v) + h(u) - h(v) неотрицательна.


Далее для прокладки кратчайших путей используется алгоритм Дейкстры.


Орграф для алгоритма Джонсона лучше представит  в виде списков смежности. Это представление больше подходит для разреженных графов.

Алгоритм возвращает матрицу D = |dij| размера |V| * |V|, где dij = d(i, j), или возвращает сообщение о том, что граф имеет отрицательный цикл. Вершины нумеруются от 1 до |V|.

            Johnson(G)

1.  Создать граф G`, для которого V[G`] = V[G]È{S} и E[G`] = E[G]È{S, v}: vÎV[G]

2.  if Bellman_Ford(G`, w, S) = FALSE

3.      then печать "имеется цикл отрицательного веса"

4.      else for  (для) каждой вершины vÎV[G`]

5.                  do h(v)ßd[v]              d[v] вычислено в Bellman_Ford

6.             for (для) каждого ребра (u, v)ÎE[G`]

7.                  do ~w(u, v)ßw(u, v) + h(u) - h(v)

8.             for (для) каждой вершины uÎV[G]

9.                   do Dijkstra(G, ~w, u)         вычисление |~d|

10.                          for (для) каждой вершины vÎV[G]

11.                                 do d ß ~d[v] + h[v] - h[u]       вычисление |d|