1. Практическое занятие 14.
Поиск кратчайшего пути
1.
2.
3.
4.
Теоретические сведения
Контрольные вопросы
Указания по выполнению заданий
Задания
2. Теоретические сведения
В задаче о кратчайшем пути задается взвешенный
ориентированный граф G = (V, Е) с весовой функцией
w: Е → R, отображающей ребра на их веса, значения
которых выражаются действительными числами. Вес
пути
p = (v0, v1,..., vN) равен суммарному весу
входящих в него ребер:
N
w( p ) = w(vi −, vi )
∑
1
i=
1
Вес кратчайшего пути из вершины u в вершину v
определяется соотношением
{
}
p
min w( p ) : u → если имеется путь от u к v,
v
δ(u , v) =
∞
в противном случае.
Тогда по определению кратчайший путь из вершины u в
вершину v – это любой путь, вес которого
удовлетворяет соотношению w(р) = δ(u, v).
3. Теоретические сведения
Рассмотрим алгоритмы решения задачи о кратчайшем пути из
одной вершины, в которой для заданного графа G = (V, Е)
требуется найти кратчайший путь, который начинается в
определенной исходной вершине s ∈ V (для краткости будем
именовать ее истоком) и заканчивается в каждой из вершин v
∈ V. Во всех описанных далее алгоритмах предполагается,
что ориентированный граф G хранится в виде списков
смежных вершин. Кроме того, вместе с каждым ребром
хранится его вес, так что при просмотре каждого списка
смежности вес каждого из его ребер можно определить в
течение времени O(1).
В некоторых алгоритмах поиска кратчайшего пути (например, в
алгоритме Дейкстры) используется метод релаксации, или
ослабления. Для каждой вершины 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
Пример 1. Алгоритм Дейкстры. Алгоритм Дейкстры решает задачу о
кратчайшем пути из одной вершины во взвешенном
ориентированном графе G = (V, Е) в том случае, когда веса ребер
неотрицательны, т.е. для всех ребер (u, v) ∈ Е выполняется
неравенство w(u, v) ≥ 0.
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)
6. Теоретические сведения
В алгоритме Дейкстры поддерживается множество вершин S,
для которых уже вычислены окончательные веса кратчайших
путей к ним из истока s. В этом алгоритме поочередно
выбирается вершина u ∈ V – S, которой на данном этапе
соответствует минимальная оценка кратчайшего пути. После
добавления этой вершины u в множество S производится
ослабление всех исходящих из нее ребер. По завершении
обработки алгоритмом Дейкстры взвешенного
ориентированного графа G = (V, Е) с неотрицательной
весовой функцией w и истоком s для всех вершин u ∈ V
выполняется равенство d[u] = δ(s, u).
В приведенной реализации алгоритма Дейкстры используется
неубывающая очередь с приоритетами Q, состоящая из
вершин, в роли ключей для которых выступают значения d.
Очередь с приоритетами – это структура данных,
предназначенная для обслуживания множества S, с каждым
элементом которого связано определенное значение,
называющееся ключом (key). В неубывающей очереди с
приоритетами поддерживаются следующие операции.
7. Теоретические сведения
• Операция Insert(S, x) вставляет элемент x в множество S. Эту
операцию можно записать как S ← S ∪ {x}.
• Операция Minimum(S) возвращает элемент множества S с
наименьшим ключом.
• Операция Extract_Min(S) возвращает элемент с наименьшим
ключом, удаляя его при этом из множества S.
• Операция Decrease_Key(S, x, k) уменьшает значение ключа,
соответствующего элементу x, путем его замены ключом со
значением k. Предполагается, что величина k не больше текущего
ключа элемента x.
Пример 2. Алгоритм Флойда-Уоршалла. Будем считать, что весовая
функция w задана в виде матрицы W.
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
6.
do 7. return D(n)
8. Теоретические сведения
В алгоритме Флойда-Уоршалла рассматриваются
промежуточные вершины кратчайшего пути. Промежуточной
вершиной простого пути
p = (v1, v2, …, vN) называется
произвольная вершина, отличная от v1 и vN, т.е. это любая
вершина из множества {v2, v3,..., vN – 1}.
Для построения кратчайших путей в алгоритме ФлойдаУоршалла нужно на основе матрицы D, содержащей веса
кратчайших путей, вычислить матрицу предшествования П =
(πij). Если задана матрица предшествования П, то вывести
вершины на указанном кратчайшем пути можно с помощью
процедуры 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
9. Теоретические сведения
Для получения матрицу предшествования П нужно вычислить
последовательность матриц П(0), П(1), ..., П(n), где П(n) = П,
а элемент определяется как предшественник вершины j на
кратчайшем пути из вершины i, все промежуточные
вершины которого принадлежат множеству {1, 2, ..., k}.
Можно дать следующее рекурсивное определение величины .
Если k = 0, то
,
NIL если i = j или wij =∞
i
если i ≠ j и wij <∞
.
(
πij0) =
При k ≥ 1
(
πijk )
(
1
(
1
(k 1
ijk − ) если d ijk − ) ≤d ikk − ) +d kj − ) ,
π( 1
=
(
(
(
π( k −1) если d ijk −1) >d ikk −1) +d kjk −1) .
kj
10. Контрольные вопросы
1.
2.
3.
4.
5.
6.
7.
8.
9.
Вес пути.
Вес кратчайшего пути.
Постановка задачи поиска кратчайшего пути.
Метод релаксации.
Алгоритм Дейкстры.
Неубывающая очередь с приоритетами.
Операции над очередью с приоритетами.
Алгоритм Флойда-Уоршалла.
Вычисление матрицы предшествования в алгоритме
Флойда-Уоршалла.
10. Вывод кратчайших путей по матрице
предшествования.
11. Указания по выполнению заданий
1.
2.
3.
4.
Получить задание
Получить решение задачи.
Подготовить отчет по выполнению задания. Отчет
должен включать задание и описание этапов
выполнения задания.
Ответить на вопросы по выполнению задания и
контрольные вопросы
12. Задания
1. Выполнить анализ сложности алгоритма Дейкстры.
2. Дополнить алгоритм Дейкстры выводом кратчайшего
пути из истока.
3. Описать алгоритм Дейкстры на языке высокого
уровня (например, на языке C).
4. Выполнить анализ сложности алгоритма ФлойдаУоршалла.
5. Описать алгоритм Флойда-Уоршалла на языке
высокого уровня (например, на языке C).
6. Разработать алгоритм поиска кратчайшего пути на
основе какого-либо из алгоритмов обхода графа.
Выполнить анализ сложности и сравнить с
алгоритмами Дейкстры и Флойда-Уоршалла.
7. Модифицировать приведенные алгоритмы для
случая отрицательных весов.