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

Задача нахождения кратчайших путей из всех вершин формирует таблицу весов, в которой на пересечении строки i и столбца j, находится вес кратчайшего пути из i в j информация о самом пути.

Эту задачу можно решить для орграфа G = (V, E) с заданной весовой функцией w: EàR если |V| раз применить алгоритм поиска кратчайших путей для всех вершин поочередно. Если ребра имеют неотрицательные веса, то можно применить алгоритм Дейкстры. Общее время алгоритма составит O(V(V2+E)) = O(V3) или O(VE log V), если в алгоритме Дейкстры используется очередь с приоритетами. Для разреженных графов это вполне допустимо.

Если в орграфе есть ребра с отрицательным весом, то можно использовать более медленный алгоритм Беллмана - Форда и общее время составит O(V2E) а для плотных графов O(V4).

Изобретены более быстрые алгоритмы. Наиболее удобны эти алгоритмы для орграфов, представленных матрицами. Исходными данными для этих алгоритмов является матрица весов взвешенного орграфа W = (wij) элементы равны:


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

Алгоритм формирует матрицу D = (dij), элементы которой dij = d(i, j) (вес кратчайшего пути). Кроме того, формируется матрица предшествования P =(pij), в которой pij является вершиной

предшествующей вершине j на одном из кратчайших путей из i j. pij = NIL для i = j или, если пути из i в j нет. Для каждой вершины iÎV можно выделить подграф предшествования Gp, i = (Vp, i, Ep, i), где Vp, i, = {jÎV: pij ¹ NIL} È {i}

НЕ нашли? Не то? Что вы ищете?

Ep, i, = {(pij, j): jÎ Vp, i, и pij ¹ NIL}.

Имея такую матрицу, можно построить путь из вершины i в j:

All_Pathes(P, i, j)

1.  if i = j

2.  then печать i

3.  else if pij = NIL

4.  then печать "пути из i в j нет"

5.  else All_Pathes(P, i, pi, j )

6.  печать j

Алгоритм Флойда – Уоршолла.

Алгоритм Флойда - Уоршолла является алгоритмом динамического программирования. Алгоритм допускает ребра с отрицательным весом, но не допускает циклы с отрицательным весом.

Строение кратчайшего пути.

Введем понятие промежуточной вершины: если есть простой путь p = <v1, v2, ..., vi >, то вершины v2, v3, ... vi-1 называются промежуточными.

Для простоты будем обозначать вершины графа G числами 1, 2,..., n. Рассмотрим подмножество вершин k £ n. Для каждой пары вершин i, j Î V рассмотрим все пути из i, j включающие в путь только вершины {1, 2,...,k}.

Среди них можно выделить путь с минимальным весом. Вес этого пути можно получить, зная вес минимального пути между i, j, включающего вершины {1, 2,...,k-1}.

При добавлении вершины k между вершинами i и j, новый минимальный путь может содержать вершину k в качестве промежуточной или нет.

Если вершина k не вошла в минимальный путь, то новый минимальный путь включает в себя минимальный путь для множества {1, 2,...,k-1}.

Если вершина k промежуточная, то новый минимальный путь разбивается на 2 участка.


Минимальные пути p1 и p2 включают в себя вершины {1, 2, ..., k-1}, которые также должны быть минимальны.

Исходя из этих рассуждений, можно выделить рекуррентное соотношение между решениями подзадач.

Пусть d ij (k) - вес кратчайшего пути из вершины i в j с промежуточными вершинами из подмножества {1, 2,...,k}.

При k = 0прормежуточных путей нет и d ij (0) =wij

В общем случае:


Матрица D(n) = d(n)ij содержит искомое решение, т. е. d(n)ij=d(i, j) для всех i, j Î V, т. к. разрешены любые промежуточные вершины.

Помимо весов кратчайших путей параллельно в матрице p фиксируются p(k)ij


Вычисление кратчайших путей снизу вверх.

Входом алгоритма является матрица весов, результатом - матрица весов кратчайших путей D(n).

Floyd_Warshall (W)

1.  n← |V[G]|

2.  D(0) ←W

3.  for i←1 to n

4.  for j←1 to n

5.  if (wij¹¥) then pij←i

6.  pii←nil

7.  else pii←nil

8.  for k←1 to n

9.  do for i←1 to n

10.  do for j←1 to n

11.  do if (d(k)ij) ←min (d(k-1)ij, d(k-1)ik + d(k-1)kj)

12.  return D(n)

Пусть дан граф:




Транзитивное замыкание орграфа.

Задача о транзитивном замыкании состоит в следующем: дан орграф G=(V, E) с вершинами 1, 2, ...,n. Требуется определить для любой пары вершин i, j ÎV существует ли в графе путь из вершины i в вершину j. Транзитивным замыканием орграфа G называется орграф G*=(V, E), где E*={(i, j): в графе G существует путь из i в j}. Транзитивное замыкание можно вычислять за время O(n3) при помощи алгоритма Флойда - Уоршолла считая, что все ребра имеют вес 1. В результате dij<n, если между вершинами i и j существует путь, или dij=¥, если между вершинами i и j пути нет. Для решения задачи используется модифицированный алгоритм Флойда - Улршолла. В нем операции “min” и “+” заменяются на логические операции И (Ù) и ИЛИ (Ú). Положим t(k)ij=1, если в графе G существует путь из i в j с промежуточными вершинами из множества {1, 2,...,k} и t(k)ij=0, если такого пути нет. Ребро (i, j) принадлежит транзитивному замыканию G* тогда и только тогда, когда t(n)ij=1.


Для 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|

12.  return D

Общее время работы алгоритма - O(VE log V), что меньше, чем в алгоритме Флойда - Уоршолла (O(V3)).

Паросочетания в двудольном графе.

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

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

Задача нахождения максимального паросочетания заключается в поиске максимального подмножества инцидентных ребер.

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

Примером задачи поиска максимального паросочетания является следующая задача:

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


Требуется найти такое распределение курсов, чтобы на курс пришлось не более одного преподавателя. Кроме того требуется задействовать максимальное количество преподавателей. Другая задача - задача свахи. Имеется n - женихов n - невест. У женихов и невест есть от одного до нескольких предпочитаемых кандидатур. Задача свахи устроить максимальное количество свадеб, чтобы у каждого жениха и невест была кандидатура.

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

Пусть M - паросочетания в графе G. Относительно паросочетания М вершины графа делятся на два подмножества - парные вершины {Vп} и непарные (свободные) вершины {Vнп}. Паросочетание М можно увеличить, если построить путь Р, соединяющий 2 непарные вершины и включающий в одно или несколько ребер паросочетания. Особенностью этого пути является то, что в нем чередуются ребра, не принадлежащие паросочетанию, и принадлежащему на концах пути находятся ребра ÏМ.

Имея чередующуюся цепь можно увеличит паросочетание М, удалив из него те ребра, которые входят в цепь Р, и добавить вместо них ребра, которые не входили в паросочетание. Эту операцию называют симметрической разностью множеств МDР, в которую входят в те элементы двух множеств, которые принадлежат или М или Р.

Пример: М = {1 - 6, 3 - 7, 4 - 8}

Vп = {1, 3, 4, 6, 7, 8}


Vнп = {2, 5, 9, 10}


Чередующаяся цепь: P = {2 - 6, 6 - 1, 1 - 8, 8 - 4, 4 - 9}

Симметрическая разность, МDР = {2 - 6, 1 - 8, 4 - 9, 3 - 7}. Эта разность является новым увеличенным паросочетанием.

Паросочетание будет максимальным, тогда когда не существует чередующейся цепи относительно М.

Алгоритм нахождения максимального паросочетания следующий:

Max_Pair(G)

1.  Mß0

2.  repeat

3.  PßPath_Link(G, M)

4.  MßMDP

5.  until P ¹ 0

Алгоритм Path_Link формирует чередующуюся цепь в виде множества ребер.

Алгоритм делит множество вершин на парные и непарные относительно паросочетания {Vp} и {Vnp}.

Построение чередующейся цепи напоминает алгоритм обхода в ширину и выполняется по шагам i = 0, 1, 2, ... . На нулевом шаге вершины графа делятся на подмножества {Vp} и {Vnp} и выбирается произвольно непарная вершина. Далее на 1 - м шаге выбирается ребро, не принадлежащее паросочетанию М и ведущее к парной вершине из множества {Vп}.

На 2 - м шаге и последующих четных шагах выбирается инцидентная для последней вершины пути ребро, принадлежащее М.

На 3 - м и последующих шагах выбирается инцидентное последней вершине пути ребро, не принадлежащее М. При этом, в первую очередь выбирается ребро, ведущее к свободной вершине. Если таковой нет, то выбирается ребро, не принадлежащее М и ведущие к парной вершине.

Вершины, включенные в путь Р удаляются из множества {Vнп}.

Процесс построения заканчивается, когда будет включено ребро, ведущее к непарной вершине.

Path_Link(G, M)

1.  Vpß{vÎM}

2.  VnpßV[G]\Vp

3.  Pß 0

4.  Выбор v0ÎVnp

5.  Выбор (v0, v1) D v1 ÎVp

6.  PßPÈ( v0, v1)

7.  K = 0

8.  Repeat

9.  KßK + 1

10.  Vnp = Vnp\vk

11.  Выбор (vk, vk+1) ÎM

12.  PßPÈ( vk, vk+1)

13.  KßK + 1

14.  if $ ( vk, vk+1) Ï M and vk+1ÏVp

15.  then PßPÈ{( vk, vk+1) Ï M}

16.  else p ßPÈ{( vk, vk+1) Ï M }

17.  until vk+1 Î Vp

18.  return P