SlideShare a Scribd company logo
1 of 32
Алгоритмы на графах и
деревьях (продолжение)

2. Алгоритмы кратчайшего
пути
В задаче о кратчайшем пути задается взвешенный
ориентированный граф G = (V, Е) с весовой
функцией w: Е → R, отображающей ребра на их
веса, значения которых выражаются
действительными числами. Вес пути
p = (v0,
v1,..., vN) равен суммарному весу входящих в него
N
ребер:
w( p ) = ∑w(vi −1 , vi )
i =1

Вес кратчайшего пути из вершины u в вершину v
определяется соотношением

{

}

min w( p ) : u  p v если имеется путь от u к v,
→

δ (u , v) = 
∞
в противном случае.

Тогда по определению кратчайший путь из вершины u в
вершину v – это любой путь, вес которого
удовлетворяет соотношению w(р) = δ(u, v).
Рассмотрим алгоритмы решения задачи о кратчайшем
пути из одной вершины, в которой для заданного
графа G = (V, Е) требуется найти кратчайший путь,
который начинается в определенной исходной
вершине s ∈ V (для краткости будем именовать ее
истоком) и заканчивается в каждой из вершин v ∈ V.
В описанных алгоритмах используется метод
релаксации, или ослабления. Для каждой вершины v ∈
V поддерживается атрибут d[v], представляющий
собой верхнюю границу веса, которым обладает
кратчайший путь из истока s в вершину v. Назовем
атрибут d[v] оценкой кратчайшего пути.
Инициализация оценок кратчайших путей и
предшественников производится в приведенной ниже
процедуре, время работы которой равно Θ(V):
Initialize_Single_Source(G, s)
1. for (для) каждой вершины v ∈ V[G]
2.
do d[v] ← ∞
3.
π[v] ← NIL
4. d[s] ← 0
После инициализации для всех v ∈ V π[v] = NIL,
d[s] = 0 и для всех v ∈ V – {s} d[v] = ∞.
Процесс ослабления ребра (u, v) заключается в
проверке, нельзя ли улучшить найденный до
сих пор кратчайший путь к вершине v, проведя
его через вершину u, а также в обновлении
атрибутов d[v] и π[v] при наличии такой
возможности улучшения. Ослабление может
уменьшить оценку кратчайшего пути d[v] и
обновить поле π[v] вершины v. Приведенный
ниже код выполняет ослабление ребра (u, v):
Relax(u, v, w)
1. if d[v] > d[u] + w(u, v)
2. then d[v] ← d[u) + w(u, v)
3.
π[v] ← u
В каждом из описанных алгоритмов сначала
вызывается процедура Initialize_Single_Source,
а затем производится ослабление ребер.
Алгоритм Дейкстры
Алгоритм
Дейкстры
решает
задачу
о
кратчайшем пути из одной вершины во
взвешенном ориентированном графе G = (V, Е)
в
том
случае,
когда
веса
ребер
неотрицательны.
Поэтому
будем
предполагать, что для всех ребер (u, v) ∈ Е
выполняется неравенство w(u, v) ≥ 0.
В алгоритме Дейкстры поддерживается множество вершин
S, для которых уже вычислены окончательные веса
кратчайших путей к ним из истока s. В этом алгоритме
поочередно выбирается вершина u ∈ V – S, которой на
данном этапе соответствует минимальная оценка
кратчайшего пути. После добавления этой вершины u в
множество S производится ослабление всех исходящих
из нее ребер. В приведенной ниже реализации
используется неубывающая очередь с приоритетами Q,
состоящая из вершин, в роли ключей для которых
выступают значения d.
Dijkstra(G, w, s)
1. Initialize_Single_Source(G, s)
2. S ← ∅
3. Q ← V[G]
4. while Q ≠ 0
5.
do u ← Extract_Min(Q)
6.
S ← S ∪ {u}
7.
for (для) каждой вершины v ∈ Adj[u]
8.
do Relax(u, v, w)
Работа рассматриваемого алгоритма. В строке 1 производится
обычная инициализация величин d и π, а в строке 2
инициализируется пустое множество вершин S. В этом
алгоритме поддерживается инвариант, согласно которому в
начале каждой итерации цикла while в строках 4 – 8 выполняется
равенство Q = V – S. В строке 3 неубывающая очередь с
приоритетами Q инициализируется таким образом, чтобы она
содержала все вершины множества V; поскольку в этот момент S
= 0, после выполнения строки 3 сформулированный выше
инвариант выполняется. При каждой итерации цикла while в
строках 4 – 8 вершина u извлекается из множества Q = V – S и
добавляется в множество S, в результате чего инвариант
продолжает соблюдаться. Во время первой итерации этого цикла
u = s. Т.о., вершина u имеет минимальную оценку кратчайшего
пути среди всех вершин множества V – S. Затем в строках 7 – 8
ослабляются все ребра (u, v), исходящие из вершины u. Если
текущий кратчайший путь к вершине v может быть улучшен в
результате прохождения через вершину u, выполняется
ослабление и соответствующее обновление оценки величины
d[v] и предшественника π[v]. После выполнения строки 3
вершины никогда не добавляются в множество Q и каждая
вершина извлекается из этого множества и добавляется в
множество S ровно по одному разу, поэтому количество
итераций цикла while в строках 4 – 8 равно |V|.
Теорема 1 (Корректность алгоритма Дейкстры).
По завершении обработки алгоритмом
Дейкстры взвешенного ориентированного
графа
G = (V, Е) с неотрицательной
весовой функцией w и истоком s для всех
вершин u ∈ V выполняется равенство d[u] =
δ(s, u).
Следствие 1. Если выполнить алгоритм
Дейкстры для взвешенного ориентированного
графа G = (V, E) с неотрицательной весовой
функцией w и истоком s, то по завершении
работы алгоритма подграф предшествования
Gπ является деревом кратчайших путей с
корнем в вершине s.
Очередь с приоритетами – это структура данных,
предназначенная для обслуживания множества S, с
каждым элементом которого связано определенное
значение, называющееся ключом (key). В
неубывающей очереди с приоритетами
поддерживаются следующие операции.
• Операция Insert(S, x) вставляет элемент x в множество
S. Эту операцию можно записать как S ← S ∪ {x}.
• Операция Minimum(S) возвращает элемент множества
S с наименьшим ключом.
• Операция Extract_Min(S) возвращает элемент с
наименьшим ключом, удаляя его при этом из
множества S.
• Операция Decrease_Key(S, x, k) уменьшает значение
ключа, соответствующего элементу x, путем его
замены ключом со значением k. Предполагается, что
величина k не больше текущего ключа элемента x.
Насколько быстро работает алгоритм Дейкстры? В нем
поддерживается неубывающая очередь с
приоритетами Q и тремя операциями, характерными
для очередей с приоритетами: Insert (явно
вызывается в строке 3), Extract_Min (строка 5) и
Decrease_Key (неявно присутствует в процедуре
Relax, которая вызывается в строке 8). Процедура
Insert, как и процедура Extract_Min, вызывается по
одному разу для каждой вершины. Поскольку каждая
вершина v ∈ V добавляется в множество S ровно по
одному разу, каждое ребро в списке смежных
вершин Adj[v] обрабатывается в цикле for, заданном
в строках 7 – 8, ровно по одному разу на протяжении
работы алгоритма. Так как полное количество ребер
во всех списках смежных вершин равно |Е| всего
выполняется |Е| итераций этого цикла for, а
следовательно, не более |Е| операций
Decrease_Key.
Время выполнения алгоритма Дейкстры зависит от
реализации неубывающей очереди с
приоритетами. Сначала рассмотрим случай,
когда неубывающая очередь с приоритетами
поддерживается за счет того, что все вершины
пронумерованы от 1 до |V|. Атрибут d[v] просто
помещается в элемент массива с индексом v.
Каждая операция Insert и Decrease_Key
занимает время O(1), а каждая операция
Extract_Min – время O(|V|) (поскольку в ней
производится поиск по всему массиву); в
результате полное время работы алгоритма
равно O(|V|2 + |Е|) = O(|V|2).
Алгоритм Флойда-Уоршалла
В
алгоритме
Флойда-Уоршалла
рассматриваются
"промежуточные"
вершины
кратчайшего
пути.
Промежуточной вершиной простого пути
p = (v1,v2,
…, vN) называется произвольная вершина, отличная от v1
и vN, т.е. это любая вершина из множества {v2, v3,..., vN – 1}.
Алгоритм Флойда-Уоршалла основан на следующем
наблюдении. Предположим, что граф G состоит из
вершин V = {1, 2, ..., n}. Рассмотрим подмножество
вершин {1, 2, ..., k} для некоторого k. Для произвольной
пары вершин i, j ∈ V рассмотрим все пути из вершины i в
вершину j, все промежуточные вершины которых
выбраны из множества {1, 2, ..., k}. Пусть среди этих
путей p – путь с минимальным весом (этот путь простой).
В
алгоритме
Флойда-Уоршалла
используется
взаимосвязь между путем р и кратчайшими путями из
вершины i в вершину j, все промежуточные вершины
которых принадлежат множеству {1, 2, ..., k – 1}. Эта
взаимосвязь зависит от того, является ли вершина k
промежуточной на пути р.
• Если k – не промежуточная вершина пути р, то все
промежуточные вершины этого пути принадлежат
множеству {l, 2, ..., k – 1}. Таким образом, кратчайший
путь из вершины i в вершину j со всеми
промежуточными вершинами из множества {l, 2, ..., k –
1} одновременно является кратчайшим путем из
вершины i в вершину j со всеми промежуточными
вершинами из множества {1, 2, ..., k}.
• Если k – промежуточная вершина пути р, то этот путь
можно разбить следующим образом: . Путь p1 –
кратчайший путь из вершины i в вершину k, все
промежуточные вершины которого принадлежат
множеству {1, 2, ..., k}. Поскольку k не является
промежуточной вершиной пути p1 понятно, что p1 –
кратчайший путь из вершины i в вершину k, все
промежуточные вершины которого принадлежит
множеству {1, 2, ..., k – 1}. Аналогично, p2 –
кратчайший путь из вершины k в вершину j, все
промежуточные вершины которого принадлежат
множеству {1, 2, ..., k – 1}.
Определим на основе сделанных выше наблюдений
рекурсивную формулировку оценок кратчайших
путей. Пусть – вес кратчайшего пути из вершины i в
вершину j, для которого все промежуточные
вершины принадлежат множеству {1, 2, ..., k}. Если
k = 0, то путь из вершины i в вершину j, в котором
отсутствуют промежуточные вершины с номером,
большим нуля, не содержит промежуточных
вершин вообще. Такой путь содержит не более
одного ребра, поэтому = wij. Рекурсивное
определение, которое соответствует приведенному
выше описанию, дается соотношением
(
d ijk )

если k = 0,
wij

=
(
(
k
min(d ijk −1) , d ikk −1) + d kj−1 ) если k ≥ 1.


Поскольку все промежуточные вершины
произвольного пути принадлежат множеству {1,
(
(
2, ..., n}, матрица Dijk ) = d ijk )
дает
(
конечный ответ:
d ijn ) =δ(i, j )
для всех пар вершин i, j ∈ V.
Исходя из рекуррентного соотношения, можно
составить приведенную ниже процедуру,
предназначенную для вычисления величин

(

)

(
d ijk )

в порядке возрастания k. В качестве
входных данных выступает матрица W=(wij)
0
размерами n × n, где


если i = j ,
wij = вес ориентированного ребра (i, j ) если i ≠ j и (i, j ) ∈ E ,
∞
если i ≠ j и (i, j ) ∉ E.

Процедура возвращает матрицу D(n),
содержащую веса кратчайших путей.
Floyd_Warshall(W)
1. n ← rows[W]
2. D(0) ← W
3. for k ← 1 to n
4. do for i ← 1 to n
5.
do for j ← 1 to n
(
(
(
k
d ijk ) ← min(d ijk −1) , d ikk −1) + d kj−1 )
6. do
7. 7. return D(n)
Время работы алгоритма Флойда-Уоршалла определяется
трижды вложенными друг в друга циклами for,
определенными в строках 3 – 6. Поскольку для каждого
выполнения строки 6 требуется время O(1), алгоритм
завершает работу в течение времени Θ(n3). Код этого
алгоритма Он не содержит сложных структур данных,
поэтому константа, скрытая в Θ-обозначениях, мала.
Таким образом, алгоритм Флойда-Уоршалла имеет
практическую ценность даже для входных графов
среднего размера.
Существует множество различных методов, позволяющих
строить кратчайшие пути в алгоритме Флойда-Уоршалла.
Один из них – вычисление матрицы D, содержащей веса
кратчайших путей, с последующим конструированием на
ее основе матрицы предшествования П = (πij). Этот
метод можно реализовать таким образом, чтобы время
его выполнения было равно O(n3). Если задана матрица
предшествования П, то вывести вершины на указанном
кратчайшем пути можно с помощью процедуры
Print_All_Pairs_Shortest_Path.
Print_All_Pairs_Shortest_Path(II, i, j)
1. if i = j
2. then print i
3. else if πij = NIL
4. then print "He существует пути из" i "в" j
5. else Print_All_Pairs_Shortest_Path(II, i, πij)
6. print j
Матрицу предшествования П можно так же
вычислить "на лету", как в алгоритме ФлойдаУоршалла вычисляются матрицы D(k). Точнее
говоря, вычисляется последовательность
матриц П(0), П(1), ..., П(n), где П = П(n), а элемент
определяется как предшественник вершины j
на кратчайшем пути из вершины i, все
промежуточные вершины которого
принадлежат множеству {1, 2, ..., k}.
Можно дать рекурсивное определение величины
(k
π)
. Если k = 0, то кратчайший
ij
путь из вершины i в вершину j не содержит
промежуточных вершин. Таким образом,
(
π ij0)

NIL если i = j или wij = ∞,

=
если i ≠ j и wij < ∞.
i


Если при k ≥ 1 получаем путь i → k → j, где k ≠ j, то
выбранный нами предшественник вершины j
совпадает с выбранным предшественником этой
же вершины на кратчайшем пути из вершины k,
все промежуточные вершины которого
принадлежат множеству {1, 2, ..., k – 1}.
В противном случае выбирается тот же
предшественник вершины j, который выбран
на кратчайшем пути из вершины i, у которого
все промежуточные вершины принадлежат
множеству {1, 2,..., k – 1}. Выражаясь
формально, при k ≥ 1
(
πijk )

(
1
(k 1
(k 1
 ijk − ) если d ijk − ) ≤d ik − ) +d kj − ) ,
π( 1

=
1
(
1
(
1
(
1
π( k − ) если d ijk − ) >d ikk − ) +d kjk − ) .
 kj

3. Алгоритм транзитивного
замыкания
Может возникнуть необходимость установить,
существуют ли в заданном ориентированном
графе G = (V, Е), множество вершин которого
V = {1, 2,..., n}, пути из вершины i в вершину j для
всех возможных пар вершин i, j ∈ V.
Транзитивное замыкание графа G определяется
как граф
G* = (V, E*), где E* = {(i, j) : в графе G
имеется путь из вершины i в вершину j}.
Один из способов найти транзитивное замыкание
графа в течение времени Θ(n3) – присвоить
каждому ребру из множества Е вес 1 и
выполнить алгоритм Флойда-Уоршалла. Если
путь из вершины i в вершину j существует, то мы
получим dij < n; в противном случае dij = ∞.
Другой метод включает в себя подстановку
логических операций ∨ (логическое ИЛИ) и ∧
(логическое И) вместо использующихся в
алгоритме Флойда-Уоршалла арифметических
операций min и +. Определим значение при i, j, k
= 1, 2, ..., n равным 1, если в графе G существует
путь из вершины i в вершину j, все
промежуточные вершины которого принадлежат
множеству {1, 2, ..., k}; в противном случае эта
величина равна 0. Конструируя транзитивное
замыкание G* = (V, E*), будем помещать ребро (i,
j) в множество Е* тогда и только тогда, когда
(k
(k
tij ) = 1. Рекурсивное определение величины t ij )
имеет вид
(
tij0)

0 если i ≠ j и (i, j ) ∉E ,
=
1
 если i = j или (i, j ) ∈E ,

а при k ≥ 1 выполняется соотношение
(
(
(
(k
tijk ) = tijk −1) ∨ (tikk −1) ∧ t kj −1) ).

Как и в алгоритме Флойда-Уоршалла, матрицы вычисляются в
порядке возрастания k:
Transitive_Closure(G)
1. n ← |V[G]|
2. for i ← 1 to n
3. do for j ← 1 to n
4.
do if i = j или (i, j) ∈ E[G]
5.
then ← 1
6.
else ← 0
7. for k ← 1 to n
8. do for i ← 1 to n
9.
do for j ← 1 to n
10.
do
11. return T(n)
Время работы процедуры Transitive_Closure, как и
время работы алгоритма Флойда-Уоршалла, равно
Θ(n3).
4. Минимальное остовное дерево
Для соединения множества из n контактов мы можем
использовать некоторую компоновку из n – 1 проводов,
каждый из которых соединяет два контакта.
Мы можем смоделировать эту задачу при помощи
связного неориентированного графа G = (V, Е), где V –
множество контактов, Е – множество возможных
соединений между парами контактов, и для каждого
ребра (u, v) ∈ Е задан вес w(u, v), определяющий
стоимость
(количество
необходимого
провода)
соединения u и v. Мы хотим найти ациклическое
подмножество Т ⊆ Е, которое соединяет все вершины
w(T ) = ∑w(u , v ) минимален.
и чей общий вес
( u , v )∈
T
Для решения задачи поиска минимального остовного
дерева можно воспользоваться алгоритмами Крускала
и Прима.
Алгоритм Крускала
MST_Kruskal(G, w)
1. A ← ∅
2. for (для) каждой вершины v ∈ V[G]
3. do Make_Set(v)
4. Сортируем ребра из Е в неубывающем порядке их
весов w
5. for (для) каждого (u, v) ∈ Е (в порядке возрастания
веса)
6. do if Find_Set(u) ≠ Find_Set(v)
7.
then A ← A ∪ {(u,v)}
8. Union(u, v)
9. return A
Алгоритм Крускала работает следующим образом. В
строках 1 – 3 выполняется инициализация
множества A пустым множеством и создается |V|
деревьев, каждое из которых содержит по одной
вершине. Ребра в E в строке 4 сортируются
согласно их весу в неубывающем порядке. Цикл for
в строках 5 – 8 проверяет для каждого ребра (u, v),
принадлежат ли его концы одному и тому же
дереву. Если это так, то данное ребро не может
быть добавлено к лесу без того, чтобы создать при
этом цикл, поэтому в таком случае ребро
отбрасывается. В противном случае, когда концы
ребра принадлежат разным деревьям, в строке 7
ребро (u, v) добавляется в множество A, и вершины
двух деревьев объединяются в строке 8.
Время работы оптимальной реализации алгоритма
можно оценить как O(|Е|lg|V|).
Алгоритм Прима
Алгоритм Прима очень похож на алгоритм Дейкстры для
поиска кратчайшего пути в графе. Ключевым моментом в
эффективной реализации алгоритма Прима является
выбор нового ребра для добавления в дерево. В
качестве входных данных алгоритму передаются
связный граф G и корень r минимального остовного
дерева. В процессе работы алгоритма все вершины,
которые не входят в дерево, располагаются в очереди с
приоритетами Q, основанной на значении поля key,
причем меньшее значение этого поля означает более
высокий приоритет в очереди. Для каждой вершины v
значение поля key[v] представляет собой минимальный
вес среди всех ребер, соединяющих v с вершиной в
дереве. Если ни одного такого ребра нет, считаем, что
key[v] = ∞. Поле π[v] указывает родителя v в дереве. В
процессе работы алгоритма множество A из процедуры
неявно поддерживается как A = {(v, π[v]): v ∈ V – {r} – Q}.
Когда алгоритм завершает работу, очередь с приоритетами
Q пуста и минимальным остовным деревом для G
является дерево
A = {(v, π[v]): v ∈ V – {r}}.
MST_Prim(G, w, r)
1. for (для) каждой вершины u ∈ V[G]
2. do key[u] ← ∞
3.
π[u] ← NIL
4. kеу[r] ← 0
5. Q ← V[G]
6. while Q ≠ ∅
7.
do u ← Extract_Min(Q)
8.
for (для) каждой вершины v ∈ Adj[u]
9.
do if v ∈ Q и w(u, v) < key[v]
10.
then π[v] ← u
11.
key[v] ← w(u,v)
Работа алгоритма Прима. В строках 1 – 5 ключи всех
вершин устанавливаются равными ∞ (за исключением
корня r, ключ которого равен 0, так что он оказывается
первой обрабатываемой вершиной), указателям на
родителей для всех узлов присваиваются значения NIL
и все вершины вносятся в очередь с приоритетами Q.
Алгоритм поддерживает следующий инвариант цикла,
состоящий из трех частей.
Перед каждой итерацией цикла while в строках 6 – 11
1. A = {(v, π[v]): v ∈ V – {r} – Q};
2. вершины, уже помещенные в минимальное остовное
дерево, принадлежат множеству V – Q;
3. для всех вершин v ∈ Q справедливо следующее: если
π[v] ≠ NIL, то key[v] < ∞ и key[v] – вес ребра с
минимальным весом, соединяющего v с некоторой
вершиной, уже находящейся в минимальном остовном
дереве.
Цикл for в строках 8 – 11 обновляет поля
key и π для каждой вершины v, смежной с
u и не находящейся в дереве. Это
обновление сохраняет третью часть
инварианта.
Производительность алгоритма Прима
зависит от выбранной реализации
очереди с приоритетами Q. При
оптимальной реализации общее время
работы алгоритма Прима составляет O(|Е|
+ |V|lg|V|).
5. Топологическая сортировка
Топологическую сортировку графа можно
рассматривать как такое упорядочение его
вершин вдоль горизонтальной линии, что все
ребра направлены слева направо.
Простой алгоритм топологической сортировки
ориентированного ациклического графа имеет
следующий вид:
Topological_Sort(G)
1. Вызов процедуры поиска в глубину DFS(G) для
вычисления времени завершения f[v] для каждой
вершины v
2. По завершении работы над вершиной внести ее
в начало связанного списка
3. return Связанный список вершин
Выполнить топологическую сортировку можно за время
Θ(|V| + |Е|), поскольку поиск в глубину выполняется
именно за это время, а вставка каждой из |V| вершин
в начало связанного списка занимает время O(1).
Лемма 1. Ориентированный граф G является
ациклическим тогда и только тогда, когда поиск в
глубину в G не находит в нем обратных ребер.
Предположим, что над данным ориентированным
ациклическим графом G = (V, Е) выполняется
процедура DFS, которая вычисляет время
завершения его вершин. Достаточно показать, что
если для произвольной пары разных вершин u, v ∈ V
в графе G имеется ребро от u к v, то f[v] < f[u].
Теорема 1. Процедура Topological_Sort(G) выполняет
топологическую сортировку ориентированного
ациклического графа G.

More Related Content

What's hot

Лекция №13. Графы: сильно связные компоненты и остовные деревья. Предмет "Стр...
Лекция №13. Графы: сильно связные компоненты и остовные деревья. Предмет "Стр...Лекция №13. Графы: сильно связные компоненты и остовные деревья. Предмет "Стр...
Лекция №13. Графы: сильно связные компоненты и остовные деревья. Предмет "Стр...Nikolay Grebenshikov
 
Алгоритмы и структуры данных осень 2013 лекция 8
Алгоритмы и структуры данных осень 2013 лекция 8Алгоритмы и структуры данных осень 2013 лекция 8
Алгоритмы и структуры данных осень 2013 лекция 8Technopark
 
Quantum universal enveloping algebras with idempotents and the Pierce decompo...
Quantum universal enveloping algebras with idempotents and the Pierce decompo...Quantum universal enveloping algebras with idempotents and the Pierce decompo...
Quantum universal enveloping algebras with idempotents and the Pierce decompo...Steven Duplij (Stepan Douplii)
 
лекция12
лекция12лекция12
лекция12afersh
 
равноускоренное движение
равноускоренное движениеравноускоренное движение
равноускоренное движениеorshevich
 
Лекция №16. Поиск подстрок. Предмет "Структуры и алгоритмы обработки данных"
Лекция №16. Поиск подстрок. Предмет "Структуры и алгоритмы обработки данных"Лекция №16. Поиск подстрок. Предмет "Структуры и алгоритмы обработки данных"
Лекция №16. Поиск подстрок. Предмет "Структуры и алгоритмы обработки данных"Nikolay Grebenshikov
 
20110313 systems of_typed_lambda_calculi_moskvin_lecture06
20110313 systems of_typed_lambda_calculi_moskvin_lecture0620110313 systems of_typed_lambda_calculi_moskvin_lecture06
20110313 systems of_typed_lambda_calculi_moskvin_lecture06Computer Science Club
 
Скорость роста функций
Скорость роста функцийСкорость роста функций
Скорость роста функцийDEVTYPE
 
20110522 systems of typed lambda_calculi_moskvin_lecture11
20110522 systems of typed lambda_calculi_moskvin_lecture1120110522 systems of typed lambda_calculi_moskvin_lecture11
20110522 systems of typed lambda_calculi_moskvin_lecture11Computer Science Club
 
слайды к лаб1 тмм
слайды к лаб1 тммслайды к лаб1 тмм
слайды к лаб1 тммstudent_kai
 
Тригонометрические функции числового аргумента
Тригонометрические функции числового аргументаТригонометрические функции числового аргумента
Тригонометрические функции числового аргументаFormula.co.ua
 
формула бине
формула бинеформула бине
формула бинеLeto24
 
Лекция 15 Поиск подстрок
Лекция 15 Поиск подстрокЛекция 15 Поиск подстрок
Лекция 15 Поиск подстрокsimple_people
 
практика 11
практика 11практика 11
практика 11student_kai
 
Основные принципы динамики твёрдого тела
Основные принципы динамики твёрдого телаОсновные принципы динамики твёрдого тела
Основные принципы динамики твёрдого телаTheoretical mechanics department
 
Лекция 8: Графы. Обходы графов
Лекция 8: Графы. Обходы графовЛекция 8: Графы. Обходы графов
Лекция 8: Графы. Обходы графовMikhail Kurnosov
 

What's hot (20)

Лекция №13. Графы: сильно связные компоненты и остовные деревья. Предмет "Стр...
Лекция №13. Графы: сильно связные компоненты и остовные деревья. Предмет "Стр...Лекция №13. Графы: сильно связные компоненты и остовные деревья. Предмет "Стр...
Лекция №13. Графы: сильно связные компоненты и остовные деревья. Предмет "Стр...
 
Алгоритмы и структуры данных осень 2013 лекция 8
Алгоритмы и структуры данных осень 2013 лекция 8Алгоритмы и структуры данных осень 2013 лекция 8
Алгоритмы и структуры данных осень 2013 лекция 8
 
Quantum universal enveloping algebras with idempotents and the Pierce decompo...
Quantum universal enveloping algebras with idempotents and the Pierce decompo...Quantum universal enveloping algebras with idempotents and the Pierce decompo...
Quantum universal enveloping algebras with idempotents and the Pierce decompo...
 
лекция12
лекция12лекция12
лекция12
 
равноускоренное движение
равноускоренное движениеравноускоренное движение
равноускоренное движение
 
Лекция №16. Поиск подстрок. Предмет "Структуры и алгоритмы обработки данных"
Лекция №16. Поиск подстрок. Предмет "Структуры и алгоритмы обработки данных"Лекция №16. Поиск подстрок. Предмет "Структуры и алгоритмы обработки данных"
Лекция №16. Поиск подстрок. Предмет "Структуры и алгоритмы обработки данных"
 
20110313 systems of_typed_lambda_calculi_moskvin_lecture06
20110313 systems of_typed_lambda_calculi_moskvin_lecture0620110313 systems of_typed_lambda_calculi_moskvin_lecture06
20110313 systems of_typed_lambda_calculi_moskvin_lecture06
 
Скорость роста функций
Скорость роста функцийСкорость роста функций
Скорость роста функций
 
Get Ft
Get FtGet Ft
Get Ft
 
20110522 systems of typed lambda_calculi_moskvin_lecture11
20110522 systems of typed lambda_calculi_moskvin_lecture1120110522 systems of typed lambda_calculi_moskvin_lecture11
20110522 systems of typed lambda_calculi_moskvin_lecture11
 
слайды к лаб1 тмм
слайды к лаб1 тммслайды к лаб1 тмм
слайды к лаб1 тмм
 
лекция 10
лекция 10лекция 10
лекция 10
 
Тригонометрические функции числового аргумента
Тригонометрические функции числового аргументаТригонометрические функции числового аргумента
Тригонометрические функции числового аргумента
 
формула бине
формула бинеформула бине
формула бине
 
Лекция 15 Поиск подстрок
Лекция 15 Поиск подстрокЛекция 15 Поиск подстрок
Лекция 15 Поиск подстрок
 
2014
20142014
2014
 
7
77
7
 
практика 11
практика 11практика 11
практика 11
 
Основные принципы динамики твёрдого тела
Основные принципы динамики твёрдого телаОсновные принципы динамики твёрдого тела
Основные принципы динамики твёрдого тела
 
Лекция 8: Графы. Обходы графов
Лекция 8: Графы. Обходы графовЛекция 8: Графы. Обходы графов
Лекция 8: Графы. Обходы графов
 

Viewers also liked

презентационные слайды на курсовое проектирование
презентационные слайды на курсовое проектированиепрезентационные слайды на курсовое проектирование
презентационные слайды на курсовое проектированиеstudent_kai
 
лекция 1 введение
лекция 1 введениелекция 1 введение
лекция 1 введениеstudent_kai
 
лекция№21
лекция№21лекция№21
лекция№21student_kai
 
лекция №1
лекция №1лекция №1
лекция №1student_kai
 
лекция 15 управление финансами-ч2
лекция 15 управление финансами-ч2лекция 15 управление финансами-ч2
лекция 15 управление финансами-ч2student_kai
 
лекция №8
лекция №8лекция №8
лекция №8student_kai
 
лекция 3. программирование циклов
лекция 3. программирование цикловлекция 3. программирование циклов
лекция 3. программирование цикловstudent_kai
 
лекция 13 управление уровнем услуг
лекция 13 управление уровнем услуглекция 13 управление уровнем услуг
лекция 13 управление уровнем услугstudent_kai
 
презентация лабораторных работ. часть 1
презентация лабораторных работ. часть 1презентация лабораторных работ. часть 1
презентация лабораторных работ. часть 1student_kai
 
лабораторная работа №3
лабораторная работа №3лабораторная работа №3
лабораторная работа №3student_kai
 
лекция № 6
лекция № 6лекция № 6
лекция № 6student_kai
 

Viewers also liked (20)

презентационные слайды на курсовое проектирование
презентационные слайды на курсовое проектированиепрезентационные слайды на курсовое проектирование
презентационные слайды на курсовое проектирование
 
лекция 1 введение
лекция 1 введениелекция 1 введение
лекция 1 введение
 
лекция№21
лекция№21лекция№21
лекция№21
 
Euph doc
Euph docEuph doc
Euph doc
 
лек1
лек1лек1
лек1
 
лекция 21
лекция 21лекция 21
лекция 21
 
лекция 24
лекция 24лекция 24
лекция 24
 
п9
п9п9
п9
 
лекция №1
лекция №1лекция №1
лекция №1
 
лекция 15 управление финансами-ч2
лекция 15 управление финансами-ч2лекция 15 управление финансами-ч2
лекция 15 управление финансами-ч2
 
лекция №8
лекция №8лекция №8
лекция №8
 
лекция 3. программирование циклов
лекция 3. программирование цикловлекция 3. программирование циклов
лекция 3. программирование циклов
 
лекция 13 управление уровнем услуг
лекция 13 управление уровнем услуглекция 13 управление уровнем услуг
лекция 13 управление уровнем услуг
 
презентация лабораторных работ. часть 1
презентация лабораторных работ. часть 1презентация лабораторных работ. часть 1
презентация лабораторных работ. часть 1
 
лабораторная работа №3
лабораторная работа №3лабораторная работа №3
лабораторная работа №3
 
п2 09
п2 09п2 09
п2 09
 
лекция 12
лекция 12лекция 12
лекция 12
 
Euph doc
Euph docEuph doc
Euph doc
 
лекция № 6
лекция № 6лекция № 6
лекция № 6
 
эхо 3
эхо 3эхо 3
эхо 3
 

Similar to лекция 14

Лекция 9. Поиск кратчайшего пути в графе
Лекция 9. Поиск кратчайшего пути в графеЛекция 9. Поиск кратчайшего пути в графе
Лекция 9. Поиск кратчайшего пути в графеMikhail Kurnosov
 
Лекция 9: Графы. Поиск кратчайшего пути в графе
Лекция 9: Графы. Поиск кратчайшего пути в графеЛекция 9: Графы. Поиск кратчайшего пути в графе
Лекция 9: Графы. Поиск кратчайшего пути в графеMikhail Kurnosov
 
Лекция 16 Вычислительная геометрия
Лекция 16 Вычислительная геометрияЛекция 16 Вычислительная геометрия
Лекция 16 Вычислительная геометрияsimple_people
 
функция
функцияфункция
функцияmara2101
 
20080928 structuralcomplexitytheory lecture01-02
20080928 structuralcomplexitytheory lecture01-0220080928 structuralcomplexitytheory lecture01-02
20080928 structuralcomplexitytheory lecture01-02Computer Science Club
 
Лекция №12. Графы: представление, обходы, топологическая сортировка. Предмет ...
Лекция №12. Графы: представление, обходы, топологическая сортировка. Предмет ...Лекция №12. Графы: представление, обходы, топологическая сортировка. Предмет ...
Лекция №12. Графы: представление, обходы, топологическая сортировка. Предмет ...Nikolay Grebenshikov
 
практика 16
практика 16практика 16
практика 16student_kai
 
практика 13
практика 13практика 13
практика 13student_kai
 
практика 15
практика 15практика 15
практика 15student_kai
 
Линейная алгебра - II
Линейная алгебра - IIЛинейная алгебра - II
Линейная алгебра - IIDEVTYPE
 
Use of eliptic curves for generating digital signature
Use of eliptic curves for generating digital signatureUse of eliptic curves for generating digital signature
Use of eliptic curves for generating digital signatureAndrei Poliakov
 
20101028 proof complexity_hirsch_lecture06
20101028 proof complexity_hirsch_lecture0620101028 proof complexity_hirsch_lecture06
20101028 proof complexity_hirsch_lecture06Computer Science Club
 
Прямолинейное движение. ОТВЕТЫ И РЕШЕНИЯ.
Прямолинейное движение. ОТВЕТЫ И РЕШЕНИЯ.Прямолинейное движение. ОТВЕТЫ И РЕШЕНИЯ.
Прямолинейное движение. ОТВЕТЫ И РЕШЕНИЯ.Garik Yenokyan
 
554 1 алгебра. 9кл.-кузнецова, муравьева и др_минск, 2014 -287с
554 1  алгебра. 9кл.-кузнецова, муравьева и др_минск, 2014 -287с554 1  алгебра. 9кл.-кузнецова, муравьева и др_минск, 2014 -287с
554 1 алгебра. 9кл.-кузнецова, муравьева и др_минск, 2014 -287сdfdkfjs
 

Similar to лекция 14 (20)

Лекция 9. Поиск кратчайшего пути в графе
Лекция 9. Поиск кратчайшего пути в графеЛекция 9. Поиск кратчайшего пути в графе
Лекция 9. Поиск кратчайшего пути в графе
 
Лекция 9: Графы. Поиск кратчайшего пути в графе
Лекция 9: Графы. Поиск кратчайшего пути в графеЛекция 9: Графы. Поиск кратчайшего пути в графе
Лекция 9: Графы. Поиск кратчайшего пути в графе
 
6.0a
6.0a6.0a
6.0a
 
Funkciya 1
Funkciya 1Funkciya 1
Funkciya 1
 
лекция 15
лекция 15лекция 15
лекция 15
 
Лекция 16 Вычислительная геометрия
Лекция 16 Вычислительная геометрияЛекция 16 Вычислительная геометрия
Лекция 16 Вычислительная геометрия
 
функция
функцияфункция
функция
 
20080928 structuralcomplexitytheory lecture01-02
20080928 structuralcomplexitytheory lecture01-0220080928 structuralcomplexitytheory lecture01-02
20080928 structuralcomplexitytheory lecture01-02
 
5
55
5
 
Лекция №12. Графы: представление, обходы, топологическая сортировка. Предмет ...
Лекция №12. Графы: представление, обходы, топологическая сортировка. Предмет ...Лекция №12. Графы: представление, обходы, топологическая сортировка. Предмет ...
Лекция №12. Графы: представление, обходы, топологическая сортировка. Предмет ...
 
String
StringString
String
 
практика 16
практика 16практика 16
практика 16
 
практика 13
практика 13практика 13
практика 13
 
Основы MATLAB. Численные методы
Основы MATLAB. Численные методыОсновы MATLAB. Численные методы
Основы MATLAB. Численные методы
 
практика 15
практика 15практика 15
практика 15
 
Линейная алгебра - II
Линейная алгебра - IIЛинейная алгебра - II
Линейная алгебра - II
 
Use of eliptic curves for generating digital signature
Use of eliptic curves for generating digital signatureUse of eliptic curves for generating digital signature
Use of eliptic curves for generating digital signature
 
20101028 proof complexity_hirsch_lecture06
20101028 proof complexity_hirsch_lecture0620101028 proof complexity_hirsch_lecture06
20101028 proof complexity_hirsch_lecture06
 
Прямолинейное движение. ОТВЕТЫ И РЕШЕНИЯ.
Прямолинейное движение. ОТВЕТЫ И РЕШЕНИЯ.Прямолинейное движение. ОТВЕТЫ И РЕШЕНИЯ.
Прямолинейное движение. ОТВЕТЫ И РЕШЕНИЯ.
 
554 1 алгебра. 9кл.-кузнецова, муравьева и др_минск, 2014 -287с
554 1  алгебра. 9кл.-кузнецова, муравьева и др_минск, 2014 -287с554 1  алгебра. 9кл.-кузнецова, муравьева и др_минск, 2014 -287с
554 1 алгебра. 9кл.-кузнецова, муравьева и др_минск, 2014 -287с
 

More from student_kai

презентация
презентацияпрезентация
презентацияstudent_kai
 
презентации продолжение банкета
презентации продолжение банкетапрезентации продолжение банкета
презентации продолжение банкетаstudent_kai
 
основы программирования на языке C
основы программирования на языке Cосновы программирования на языке C
основы программирования на языке Cstudent_kai
 
презентация курсовой работы
презентация курсовой работыпрезентация курсовой работы
презентация курсовой работыstudent_kai
 
лекция№34
лекция№34лекция№34
лекция№34student_kai
 
лекция№32
лекция№32лекция№32
лекция№32student_kai
 
лекция№33
лекция№33лекция№33
лекция№33student_kai
 
лекция№31
лекция№31лекция№31
лекция№31student_kai
 
лекция№30
лекция№30лекция№30
лекция№30student_kai
 
лекция№29
лекция№29лекция№29
лекция№29student_kai
 
лекция№28
лекция№28лекция№28
лекция№28student_kai
 
лекция№27
лекция№27лекция№27
лекция№27student_kai
 
лекция№26
лекция№26лекция№26
лекция№26student_kai
 
лекция№25
лекция№25лекция№25
лекция№25student_kai
 
лекция№25
лекция№25лекция№25
лекция№25student_kai
 
лекция№24
лекция№24лекция№24
лекция№24student_kai
 
лекция№23
лекция№23лекция№23
лекция№23student_kai
 
лекция№22
лекция№22лекция№22
лекция№22student_kai
 
лекция№20
лекция№20лекция№20
лекция№20student_kai
 
лекция№19
лекция№19лекция№19
лекция№19student_kai
 

More from student_kai (20)

презентация
презентацияпрезентация
презентация
 
презентации продолжение банкета
презентации продолжение банкетапрезентации продолжение банкета
презентации продолжение банкета
 
основы программирования на языке C
основы программирования на языке Cосновы программирования на языке C
основы программирования на языке C
 
презентация курсовой работы
презентация курсовой работыпрезентация курсовой работы
презентация курсовой работы
 
лекция№34
лекция№34лекция№34
лекция№34
 
лекция№32
лекция№32лекция№32
лекция№32
 
лекция№33
лекция№33лекция№33
лекция№33
 
лекция№31
лекция№31лекция№31
лекция№31
 
лекция№30
лекция№30лекция№30
лекция№30
 
лекция№29
лекция№29лекция№29
лекция№29
 
лекция№28
лекция№28лекция№28
лекция№28
 
лекция№27
лекция№27лекция№27
лекция№27
 
лекция№26
лекция№26лекция№26
лекция№26
 
лекция№25
лекция№25лекция№25
лекция№25
 
лекция№25
лекция№25лекция№25
лекция№25
 
лекция№24
лекция№24лекция№24
лекция№24
 
лекция№23
лекция№23лекция№23
лекция№23
 
лекция№22
лекция№22лекция№22
лекция№22
 
лекция№20
лекция№20лекция№20
лекция№20
 
лекция№19
лекция№19лекция№19
лекция№19
 

лекция 14

  • 1. Алгоритмы на графах и деревьях (продолжение) 2. Алгоритмы кратчайшего пути
  • 2. В задаче о кратчайшем пути задается взвешенный ориентированный граф G = (V, Е) с весовой функцией w: Е → R, отображающей ребра на их веса, значения которых выражаются действительными числами. Вес пути p = (v0, v1,..., vN) равен суммарному весу входящих в него N ребер: w( p ) = ∑w(vi −1 , vi ) i =1 Вес кратчайшего пути из вершины u в вершину v определяется соотношением { } min w( p ) : u  p v если имеется путь от u к v, →  δ (u , v) =  ∞ в противном случае. 
  • 3. Тогда по определению кратчайший путь из вершины u в вершину v – это любой путь, вес которого удовлетворяет соотношению w(р) = δ(u, v). Рассмотрим алгоритмы решения задачи о кратчайшем пути из одной вершины, в которой для заданного графа G = (V, Е) требуется найти кратчайший путь, который начинается в определенной исходной вершине s ∈ V (для краткости будем именовать ее истоком) и заканчивается в каждой из вершин v ∈ V. В описанных алгоритмах используется метод релаксации, или ослабления. Для каждой вершины v ∈ V поддерживается атрибут d[v], представляющий собой верхнюю границу веса, которым обладает кратчайший путь из истока s в вершину v. Назовем атрибут d[v] оценкой кратчайшего пути. Инициализация оценок кратчайших путей и предшественников производится в приведенной ниже процедуре, время работы которой равно Θ(V):
  • 4. Initialize_Single_Source(G, s) 1. for (для) каждой вершины v ∈ V[G] 2. do d[v] ← ∞ 3. π[v] ← NIL 4. d[s] ← 0 После инициализации для всех v ∈ V π[v] = NIL, d[s] = 0 и для всех v ∈ V – {s} d[v] = ∞. Процесс ослабления ребра (u, v) заключается в проверке, нельзя ли улучшить найденный до сих пор кратчайший путь к вершине v, проведя его через вершину u, а также в обновлении атрибутов d[v] и π[v] при наличии такой возможности улучшения. Ослабление может уменьшить оценку кратчайшего пути d[v] и обновить поле π[v] вершины v. Приведенный ниже код выполняет ослабление ребра (u, v):
  • 5. Relax(u, v, w) 1. if d[v] > d[u] + w(u, v) 2. then d[v] ← d[u) + w(u, v) 3. π[v] ← u В каждом из описанных алгоритмов сначала вызывается процедура Initialize_Single_Source, а затем производится ослабление ребер. Алгоритм Дейкстры Алгоритм Дейкстры решает задачу о кратчайшем пути из одной вершины во взвешенном ориентированном графе G = (V, Е) в том случае, когда веса ребер неотрицательны. Поэтому будем предполагать, что для всех ребер (u, v) ∈ Е выполняется неравенство w(u, v) ≥ 0.
  • 6. В алгоритме Дейкстры поддерживается множество вершин S, для которых уже вычислены окончательные веса кратчайших путей к ним из истока s. В этом алгоритме поочередно выбирается вершина u ∈ V – S, которой на данном этапе соответствует минимальная оценка кратчайшего пути. После добавления этой вершины u в множество S производится ослабление всех исходящих из нее ребер. В приведенной ниже реализации используется неубывающая очередь с приоритетами Q, состоящая из вершин, в роли ключей для которых выступают значения d. Dijkstra(G, w, s) 1. Initialize_Single_Source(G, s) 2. S ← ∅ 3. Q ← V[G] 4. while Q ≠ 0 5. do u ← Extract_Min(Q) 6. S ← S ∪ {u} 7. for (для) каждой вершины v ∈ Adj[u] 8. do Relax(u, v, w)
  • 7. Работа рассматриваемого алгоритма. В строке 1 производится обычная инициализация величин d и π, а в строке 2 инициализируется пустое множество вершин S. В этом алгоритме поддерживается инвариант, согласно которому в начале каждой итерации цикла while в строках 4 – 8 выполняется равенство Q = V – S. В строке 3 неубывающая очередь с приоритетами Q инициализируется таким образом, чтобы она содержала все вершины множества V; поскольку в этот момент S = 0, после выполнения строки 3 сформулированный выше инвариант выполняется. При каждой итерации цикла while в строках 4 – 8 вершина u извлекается из множества Q = V – S и добавляется в множество S, в результате чего инвариант продолжает соблюдаться. Во время первой итерации этого цикла u = s. Т.о., вершина u имеет минимальную оценку кратчайшего пути среди всех вершин множества V – S. Затем в строках 7 – 8 ослабляются все ребра (u, v), исходящие из вершины u. Если текущий кратчайший путь к вершине v может быть улучшен в результате прохождения через вершину u, выполняется ослабление и соответствующее обновление оценки величины d[v] и предшественника π[v]. После выполнения строки 3 вершины никогда не добавляются в множество Q и каждая вершина извлекается из этого множества и добавляется в множество S ровно по одному разу, поэтому количество итераций цикла while в строках 4 – 8 равно |V|.
  • 8. Теорема 1 (Корректность алгоритма Дейкстры). По завершении обработки алгоритмом Дейкстры взвешенного ориентированного графа G = (V, Е) с неотрицательной весовой функцией w и истоком s для всех вершин u ∈ V выполняется равенство d[u] = δ(s, u). Следствие 1. Если выполнить алгоритм Дейкстры для взвешенного ориентированного графа G = (V, E) с неотрицательной весовой функцией w и истоком s, то по завершении работы алгоритма подграф предшествования Gπ является деревом кратчайших путей с корнем в вершине s.
  • 9. Очередь с приоритетами – это структура данных, предназначенная для обслуживания множества S, с каждым элементом которого связано определенное значение, называющееся ключом (key). В неубывающей очереди с приоритетами поддерживаются следующие операции. • Операция Insert(S, x) вставляет элемент x в множество S. Эту операцию можно записать как S ← S ∪ {x}. • Операция Minimum(S) возвращает элемент множества S с наименьшим ключом. • Операция Extract_Min(S) возвращает элемент с наименьшим ключом, удаляя его при этом из множества S. • Операция Decrease_Key(S, x, k) уменьшает значение ключа, соответствующего элементу x, путем его замены ключом со значением k. Предполагается, что величина k не больше текущего ключа элемента x.
  • 10. Насколько быстро работает алгоритм Дейкстры? В нем поддерживается неубывающая очередь с приоритетами Q и тремя операциями, характерными для очередей с приоритетами: Insert (явно вызывается в строке 3), Extract_Min (строка 5) и Decrease_Key (неявно присутствует в процедуре Relax, которая вызывается в строке 8). Процедура Insert, как и процедура Extract_Min, вызывается по одному разу для каждой вершины. Поскольку каждая вершина v ∈ V добавляется в множество S ровно по одному разу, каждое ребро в списке смежных вершин Adj[v] обрабатывается в цикле for, заданном в строках 7 – 8, ровно по одному разу на протяжении работы алгоритма. Так как полное количество ребер во всех списках смежных вершин равно |Е| всего выполняется |Е| итераций этого цикла for, а следовательно, не более |Е| операций Decrease_Key.
  • 11. Время выполнения алгоритма Дейкстры зависит от реализации неубывающей очереди с приоритетами. Сначала рассмотрим случай, когда неубывающая очередь с приоритетами поддерживается за счет того, что все вершины пронумерованы от 1 до |V|. Атрибут d[v] просто помещается в элемент массива с индексом v. Каждая операция Insert и Decrease_Key занимает время O(1), а каждая операция Extract_Min – время O(|V|) (поскольку в ней производится поиск по всему массиву); в результате полное время работы алгоритма равно O(|V|2 + |Е|) = O(|V|2).
  • 12. Алгоритм Флойда-Уоршалла В алгоритме Флойда-Уоршалла рассматриваются "промежуточные" вершины кратчайшего пути. Промежуточной вершиной простого пути p = (v1,v2, …, vN) называется произвольная вершина, отличная от v1 и vN, т.е. это любая вершина из множества {v2, v3,..., vN – 1}. Алгоритм Флойда-Уоршалла основан на следующем наблюдении. Предположим, что граф G состоит из вершин V = {1, 2, ..., n}. Рассмотрим подмножество вершин {1, 2, ..., k} для некоторого k. Для произвольной пары вершин i, j ∈ V рассмотрим все пути из вершины i в вершину j, все промежуточные вершины которых выбраны из множества {1, 2, ..., k}. Пусть среди этих путей p – путь с минимальным весом (этот путь простой). В алгоритме Флойда-Уоршалла используется взаимосвязь между путем р и кратчайшими путями из вершины i в вершину j, все промежуточные вершины которых принадлежат множеству {1, 2, ..., k – 1}. Эта взаимосвязь зависит от того, является ли вершина k промежуточной на пути р.
  • 13. • Если k – не промежуточная вершина пути р, то все промежуточные вершины этого пути принадлежат множеству {l, 2, ..., k – 1}. Таким образом, кратчайший путь из вершины i в вершину j со всеми промежуточными вершинами из множества {l, 2, ..., k – 1} одновременно является кратчайшим путем из вершины i в вершину j со всеми промежуточными вершинами из множества {1, 2, ..., k}. • Если k – промежуточная вершина пути р, то этот путь можно разбить следующим образом: . Путь p1 – кратчайший путь из вершины i в вершину k, все промежуточные вершины которого принадлежат множеству {1, 2, ..., k}. Поскольку k не является промежуточной вершиной пути p1 понятно, что p1 – кратчайший путь из вершины i в вершину k, все промежуточные вершины которого принадлежит множеству {1, 2, ..., k – 1}. Аналогично, p2 – кратчайший путь из вершины k в вершину j, все промежуточные вершины которого принадлежат множеству {1, 2, ..., k – 1}.
  • 14. Определим на основе сделанных выше наблюдений рекурсивную формулировку оценок кратчайших путей. Пусть – вес кратчайшего пути из вершины i в вершину j, для которого все промежуточные вершины принадлежат множеству {1, 2, ..., k}. Если k = 0, то путь из вершины i в вершину j, в котором отсутствуют промежуточные вершины с номером, большим нуля, не содержит промежуточных вершин вообще. Такой путь содержит не более одного ребра, поэтому = wij. Рекурсивное определение, которое соответствует приведенному выше описанию, дается соотношением ( d ijk ) если k = 0, wij  = ( ( k min(d ijk −1) , d ikk −1) + d kj−1 ) если k ≥ 1.  
  • 15. Поскольку все промежуточные вершины произвольного пути принадлежат множеству {1, ( ( 2, ..., n}, матрица Dijk ) = d ijk ) дает ( конечный ответ: d ijn ) =δ(i, j ) для всех пар вершин i, j ∈ V. Исходя из рекуррентного соотношения, можно составить приведенную ниже процедуру, предназначенную для вычисления величин ( ) ( d ijk ) в порядке возрастания k. В качестве входных данных выступает матрица W=(wij) 0 размерами n × n, где  если i = j , wij = вес ориентированного ребра (i, j ) если i ≠ j и (i, j ) ∈ E , ∞ если i ≠ j и (i, j ) ∉ E. 
  • 16. Процедура возвращает матрицу D(n), содержащую веса кратчайших путей. Floyd_Warshall(W) 1. n ← rows[W] 2. D(0) ← W 3. for k ← 1 to n 4. do for i ← 1 to n 5. do for j ← 1 to n ( ( ( k d ijk ) ← min(d ijk −1) , d ikk −1) + d kj−1 ) 6. do 7. 7. return D(n)
  • 17. Время работы алгоритма Флойда-Уоршалла определяется трижды вложенными друг в друга циклами for, определенными в строках 3 – 6. Поскольку для каждого выполнения строки 6 требуется время O(1), алгоритм завершает работу в течение времени Θ(n3). Код этого алгоритма Он не содержит сложных структур данных, поэтому константа, скрытая в Θ-обозначениях, мала. Таким образом, алгоритм Флойда-Уоршалла имеет практическую ценность даже для входных графов среднего размера. Существует множество различных методов, позволяющих строить кратчайшие пути в алгоритме Флойда-Уоршалла. Один из них – вычисление матрицы D, содержащей веса кратчайших путей, с последующим конструированием на ее основе матрицы предшествования П = (πij). Этот метод можно реализовать таким образом, чтобы время его выполнения было равно O(n3). Если задана матрица предшествования П, то вывести вершины на указанном кратчайшем пути можно с помощью процедуры Print_All_Pairs_Shortest_Path.
  • 18. Print_All_Pairs_Shortest_Path(II, i, j) 1. if i = j 2. then print i 3. else if πij = NIL 4. then print "He существует пути из" i "в" j 5. else Print_All_Pairs_Shortest_Path(II, i, πij) 6. print j Матрицу предшествования П можно так же вычислить "на лету", как в алгоритме ФлойдаУоршалла вычисляются матрицы D(k). Точнее говоря, вычисляется последовательность матриц П(0), П(1), ..., П(n), где П = П(n), а элемент определяется как предшественник вершины j на кратчайшем пути из вершины i, все промежуточные вершины которого принадлежат множеству {1, 2, ..., k}.
  • 19. Можно дать рекурсивное определение величины (k π) . Если k = 0, то кратчайший ij путь из вершины i в вершину j не содержит промежуточных вершин. Таким образом, ( π ij0) NIL если i = j или wij = ∞,  = если i ≠ j и wij < ∞. i  Если при k ≥ 1 получаем путь i → k → j, где k ≠ j, то выбранный нами предшественник вершины j совпадает с выбранным предшественником этой же вершины на кратчайшем пути из вершины k, все промежуточные вершины которого принадлежат множеству {1, 2, ..., k – 1}.
  • 20. В противном случае выбирается тот же предшественник вершины j, который выбран на кратчайшем пути из вершины i, у которого все промежуточные вершины принадлежат множеству {1, 2,..., k – 1}. Выражаясь формально, при k ≥ 1 ( πijk ) ( 1 (k 1 (k 1  ijk − ) если d ijk − ) ≤d ik − ) +d kj − ) , π( 1  = 1 ( 1 ( 1 ( 1 π( k − ) если d ijk − ) >d ikk − ) +d kjk − ) .  kj 
  • 21. 3. Алгоритм транзитивного замыкания Может возникнуть необходимость установить, существуют ли в заданном ориентированном графе G = (V, Е), множество вершин которого V = {1, 2,..., n}, пути из вершины i в вершину j для всех возможных пар вершин i, j ∈ V. Транзитивное замыкание графа G определяется как граф G* = (V, E*), где E* = {(i, j) : в графе G имеется путь из вершины i в вершину j}. Один из способов найти транзитивное замыкание графа в течение времени Θ(n3) – присвоить каждому ребру из множества Е вес 1 и выполнить алгоритм Флойда-Уоршалла. Если путь из вершины i в вершину j существует, то мы получим dij < n; в противном случае dij = ∞.
  • 22. Другой метод включает в себя подстановку логических операций ∨ (логическое ИЛИ) и ∧ (логическое И) вместо использующихся в алгоритме Флойда-Уоршалла арифметических операций min и +. Определим значение при i, j, k = 1, 2, ..., n равным 1, если в графе G существует путь из вершины i в вершину j, все промежуточные вершины которого принадлежат множеству {1, 2, ..., k}; в противном случае эта величина равна 0. Конструируя транзитивное замыкание G* = (V, E*), будем помещать ребро (i, j) в множество Е* тогда и только тогда, когда (k (k tij ) = 1. Рекурсивное определение величины t ij ) имеет вид
  • 23. ( tij0) 0 если i ≠ j и (i, j ) ∉E , = 1  если i = j или (i, j ) ∈E , а при k ≥ 1 выполняется соотношение ( ( ( (k tijk ) = tijk −1) ∨ (tikk −1) ∧ t kj −1) ). Как и в алгоритме Флойда-Уоршалла, матрицы вычисляются в порядке возрастания k: Transitive_Closure(G) 1. n ← |V[G]| 2. for i ← 1 to n 3. do for j ← 1 to n 4. do if i = j или (i, j) ∈ E[G] 5. then ← 1 6. else ← 0 7. for k ← 1 to n 8. do for i ← 1 to n 9. do for j ← 1 to n 10. do 11. return T(n)
  • 24. Время работы процедуры Transitive_Closure, как и время работы алгоритма Флойда-Уоршалла, равно Θ(n3). 4. Минимальное остовное дерево Для соединения множества из n контактов мы можем использовать некоторую компоновку из n – 1 проводов, каждый из которых соединяет два контакта. Мы можем смоделировать эту задачу при помощи связного неориентированного графа G = (V, Е), где V – множество контактов, Е – множество возможных соединений между парами контактов, и для каждого ребра (u, v) ∈ Е задан вес w(u, v), определяющий стоимость (количество необходимого провода) соединения u и v. Мы хотим найти ациклическое подмножество Т ⊆ Е, которое соединяет все вершины w(T ) = ∑w(u , v ) минимален. и чей общий вес ( u , v )∈ T
  • 25. Для решения задачи поиска минимального остовного дерева можно воспользоваться алгоритмами Крускала и Прима. Алгоритм Крускала MST_Kruskal(G, w) 1. A ← ∅ 2. for (для) каждой вершины v ∈ V[G] 3. do Make_Set(v) 4. Сортируем ребра из Е в неубывающем порядке их весов w 5. for (для) каждого (u, v) ∈ Е (в порядке возрастания веса) 6. do if Find_Set(u) ≠ Find_Set(v) 7. then A ← A ∪ {(u,v)} 8. Union(u, v) 9. return A
  • 26. Алгоритм Крускала работает следующим образом. В строках 1 – 3 выполняется инициализация множества A пустым множеством и создается |V| деревьев, каждое из которых содержит по одной вершине. Ребра в E в строке 4 сортируются согласно их весу в неубывающем порядке. Цикл for в строках 5 – 8 проверяет для каждого ребра (u, v), принадлежат ли его концы одному и тому же дереву. Если это так, то данное ребро не может быть добавлено к лесу без того, чтобы создать при этом цикл, поэтому в таком случае ребро отбрасывается. В противном случае, когда концы ребра принадлежат разным деревьям, в строке 7 ребро (u, v) добавляется в множество A, и вершины двух деревьев объединяются в строке 8. Время работы оптимальной реализации алгоритма можно оценить как O(|Е|lg|V|).
  • 27. Алгоритм Прима Алгоритм Прима очень похож на алгоритм Дейкстры для поиска кратчайшего пути в графе. Ключевым моментом в эффективной реализации алгоритма Прима является выбор нового ребра для добавления в дерево. В качестве входных данных алгоритму передаются связный граф G и корень r минимального остовного дерева. В процессе работы алгоритма все вершины, которые не входят в дерево, располагаются в очереди с приоритетами Q, основанной на значении поля key, причем меньшее значение этого поля означает более высокий приоритет в очереди. Для каждой вершины v значение поля key[v] представляет собой минимальный вес среди всех ребер, соединяющих v с вершиной в дереве. Если ни одного такого ребра нет, считаем, что key[v] = ∞. Поле π[v] указывает родителя v в дереве. В процессе работы алгоритма множество A из процедуры неявно поддерживается как A = {(v, π[v]): v ∈ V – {r} – Q}.
  • 28. Когда алгоритм завершает работу, очередь с приоритетами Q пуста и минимальным остовным деревом для G является дерево A = {(v, π[v]): v ∈ V – {r}}. MST_Prim(G, w, r) 1. for (для) каждой вершины u ∈ V[G] 2. do key[u] ← ∞ 3. π[u] ← NIL 4. kеу[r] ← 0 5. Q ← V[G] 6. while Q ≠ ∅ 7. do u ← Extract_Min(Q) 8. for (для) каждой вершины v ∈ Adj[u] 9. do if v ∈ Q и w(u, v) < key[v] 10. then π[v] ← u 11. key[v] ← w(u,v)
  • 29. Работа алгоритма Прима. В строках 1 – 5 ключи всех вершин устанавливаются равными ∞ (за исключением корня r, ключ которого равен 0, так что он оказывается первой обрабатываемой вершиной), указателям на родителей для всех узлов присваиваются значения NIL и все вершины вносятся в очередь с приоритетами Q. Алгоритм поддерживает следующий инвариант цикла, состоящий из трех частей. Перед каждой итерацией цикла while в строках 6 – 11 1. A = {(v, π[v]): v ∈ V – {r} – Q}; 2. вершины, уже помещенные в минимальное остовное дерево, принадлежат множеству V – Q; 3. для всех вершин v ∈ Q справедливо следующее: если π[v] ≠ NIL, то key[v] < ∞ и key[v] – вес ребра с минимальным весом, соединяющего v с некоторой вершиной, уже находящейся в минимальном остовном дереве.
  • 30. Цикл for в строках 8 – 11 обновляет поля key и π для каждой вершины v, смежной с u и не находящейся в дереве. Это обновление сохраняет третью часть инварианта. Производительность алгоритма Прима зависит от выбранной реализации очереди с приоритетами Q. При оптимальной реализации общее время работы алгоритма Прима составляет O(|Е| + |V|lg|V|).
  • 31. 5. Топологическая сортировка Топологическую сортировку графа можно рассматривать как такое упорядочение его вершин вдоль горизонтальной линии, что все ребра направлены слева направо. Простой алгоритм топологической сортировки ориентированного ациклического графа имеет следующий вид: Topological_Sort(G) 1. Вызов процедуры поиска в глубину DFS(G) для вычисления времени завершения f[v] для каждой вершины v 2. По завершении работы над вершиной внести ее в начало связанного списка 3. return Связанный список вершин
  • 32. Выполнить топологическую сортировку можно за время Θ(|V| + |Е|), поскольку поиск в глубину выполняется именно за это время, а вставка каждой из |V| вершин в начало связанного списка занимает время O(1). Лемма 1. Ориентированный граф G является ациклическим тогда и только тогда, когда поиск в глубину в G не находит в нем обратных ребер. Предположим, что над данным ориентированным ациклическим графом G = (V, Е) выполняется процедура DFS, которая вычисляет время завершения его вершин. Достаточно показать, что если для произвольной пары разных вершин u, v ∈ V в графе G имеется ребро от u к v, то f[v] < f[u]. Теорема 1. Процедура Topological_Sort(G) выполняет топологическую сортировку ориентированного ациклического графа G.