Дискретная математика и теория алгоритмов. Учебное пособие
.pdf
§ 5. Поиск в глубину |
31 |
|
|
доказать, что при любом поиске в глубину в неориентированном графе любое ребро является либо ребром дерева, либо обратным ребром. Тот же результат получается,
если выполнять классификацию в соответствии с тем, в каком именно виде — ( , ) или ( , ) — ребро встречается в первый раз в процессе поиска.
Время работы алгоритма
Циклы в строках 01–03 и 05–07 процедуры DFS выполняются за время (| |),
исключая время, необходимое для вызова процедуры DFS_Visit. Заметим, что процедура DFS_Visit вызывается ровно по одному разу для каждой вершины ,
поскольку она вызывается только для белых вершин, и первое, что она делает, — это окрашивает переданную в качестве параметра вершину в серый цвет. Коли-
чество итераций цикла for в строках 04–07 процедуры DFS_Visit( ) совпадает с количеством рёбер графа, выходящих из вершины . Суммарно каждое ребро гра-
фа просматривается один (для ориентированных графов) или два раза (для неориентированных графов). Поэтому общее время выполнения строк 04–07 процедуры
DFS_Visit( ) для всех вершин составляет (| |). Таким образом, время работы процедуры DFS равно (| | + | |), т.е. оно линейно.
Упражнения
1.Применить алгоритм поиска в глубину к следующим неориентированным графам, перебирая вершины в алфавитном порядке. Пометить каждое ребро как ребро дерева или обратное ребро. Написать скобочное выражение, соответствующее данному поиску в глубину.
(а)n n n (б) n n n n
@ |
@ |
|
|
n |
|
n |
|
n |
|
|
n |
|
@ |
@ |
|
|
n |
||||
n |
@ |
|
|
|
|
|
n |
@ |
|||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||||||
|
|
|
|
|
|
|
|||||||||||||||
@ |
@ |
|
n |
n |
|
@ |
@ |
|
n |
n |
|
|
|
||||||||
n |
|
n |
|
|
n |
||||||||||||||||
|
|
|
@ |
|
|
|
|
|
|
|
@ |
|
|
|
|
|
|
|
|||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2.Применить алгоритм поиска в глубину к следующим ориентированным графам, перебирая вершины в алфавитном порядке. Пометить каждое ребро как ребро дерева, прямое, обратное или перекрёстное. Написать скобочное выражение, соответствующее данному поиску в глубину.
(а)n - n (б) n - n - n
n |
|
|
I@ |
n |
|
|
|
I@ |
|
|
|
||
|
|
|
|
|
|
|
|
@ |
|
|
|||
|
|
|
|
|
@ |
|
|
|
|
|
@ ? |
||
|
|
|
|
|
|
|
|
|
? |
|
|||
|
|
|
|
6 |
|
|
|
|
- |
n |
|||
|
|
|
|
|
|
|
n |
|
|
||||
? |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
* |
|
|
|
n |
|
|
n |
|
|
@R - |
|
|
n |
|
|
|
||||||
|
|
|
|
? |
j |
? |
|
|
? |
||||
|
@ |
|
|
n |
|
|
|
|
|
|
|
||
n |
|
|
|
|
|
|
|
||||||
|
n |
|
n |
|
Y |
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3. Используя процедуру DFS, разработать алгоритм, формализующий метод прохождения лабиринта с помощью клубка ниток и мела. (Указание: представить лабиринт в виде неориентированного графа, вершины которого соответствуют помещениям лабиринта, а рёбра — проходам между соседними помещениями.)
32 |
Глава II. Алгоритмы для работы с графами |
|
|
4.Доказать, что при поиске в глубину в неориентированном графе любое реброявляется либо ребром дерева, либо обратным ребром.
5.Доказать, что при поиске в глубину ребро ( , ) является:
(а) ребром дерева или прямым ребром, если и только если [ ]< [ ]< [ ]< [ ];
(б) обратным ребром, если и только если [ ] 6 [ ] < [ ] 6 [ ];
(в) перекрёстным ребром, если и только если [ ] < [ ] < [ ] < [ ].
6.Привести пример ориентированного графа и двух его вершин и таких, что граф содержит путь из в , и [ ] < [ ] при некотором поиске в глубину в, но вершина не является потомком вершины в лесу поиска.
7.Модифицировать псевдокод процедур DFS и DFS_Visit так, чтобы поиск в
глубину расставлял метки рёбер графа в соответствии с их типами.
§ 6. Алгоритм Дейкстры
Данный параграф посвящён алгоритму решения задачи о кратчайшем пути, которая имеет естественную постановку на практике. Допустим, имеется карта дорог, на которой указаны различные населённые пункты, некоторые из них связаны дорогами. При этом на карте приведены расстояния между парами соседних пунктов, связанных дорогой. Необходимо найти кратчайший маршрут из одного пункта в другой. Карту дорог можно смоделировать в виде графа, вершины которого представляют населённые пункты, а рёбра — отрезки дорог между соседними пунктами, причём каждому ребру приписан его вес, равный расстоянию между соответствующими пунктами. Вес рёбер можно интерпретировать не как расстояние, а как временные´ интервалы, стоимость, штрафы или как любую другую величину, которая линейно накапливается по мере продвижения вдоль рёбер графа и которую необходимо оптимизировать.
Для математической формулировки задачи введём следующие определения.
Определение. Граф = , называют взвешенным, если на множестве его рёбер задана весовая функция : → R, сопоставляющая каждому ребру ( , ) некоторое действительное число ( , ) R.
Определение. Пусть = , — взвешенный ориентированный граф с неотрицательной весовой функцией : → R, т.е. ( , ) > 0 для каждого ребра ( , ) .
Весом ( ) пути = 0, 1, . . . , в графе называется суммарный вес входящих в него рёбер, т.е.
|
|
|
|
∑ |
|
( ) = |
( −1 |
, ). |
|
=1 |
|
(При = 0 считаем, что путь = 0 имеет вес ( ) = 0.)
Для произвольных , определим вес ( , ) кратчайшего пути из вершины
к вершине в графе следующим образом:
(а)Если вершина достижима из вершины в графе , то полагаем
( , ) = min{ ( ) | — путь из к в графе }.
При этом путь из к в графе назовём кратчайшим, если ( ) = ( , ).
§ 6. Алгоритм Дейкстры |
33 |
|
|
(б)Если же вершина не достижима из в графе , положим ( , ) = ∞.
Вданном параграфе рассматривается задача о кратчайшем пути из одной вершины. В этой задаче для заданного взвешенного графа = , требуется найти
кратчайший путь из определённой исходной вершины в любую другую из вершин .
Отметим, что алгоритм поиска в ширину, описанный ранее, представляет собой алгоритм поиска кратчайшего пути из исходной вершины по невзвешенному графу, т.е. графу, каждому ребру которого приписывается единичный вес. Для взвешенных графах, вообще говоря, необходим другой алгоритм.
Описание алгоритма
Алгоритм Дейкстры решает задачу о кратчайшем пути из одной вершины во взвешенном графе = , в том случае, когда веса рёбер не отрицательны. Алгоритм не только находит кратчайший путь до каждой достижимой из вершины,
но и вычисляет вес кратчайшего пути.
Как и в поиске в ширину, для представления кратчайших путей используется переменная [ ], которая называется предшественником вершины . Функция
предшественников позволяет проследить кратчайшие пути из исходной вершиныв остальные вершины графа, достижимые из . Однако до тех пор, пока алгоритм не закончил свою работу, значения не обязательно указывают кратчайшие пути. В начальный момент значение [ ] не определено для всех .
Для каждой вершины также поддерживается переменная [ ] такая, что( , ) 6 [ ]. Переменную [ ] назовём оценкой кратчайшего пути. Cчитается, что
вмомент запуска алгоритма имеет место [ ] = 0 и [ ] = ∞ для всех { }.
Валгоритме используется процесс ослабления (релаксации) рёбер, который мы опишем в виде отдельной процедуры. Ослабление ребра ( , ) заключается в
проверке, нельзя ли улучшить найденный до сих пор кратчайший путь к вершине , проведя его через вершину , а также в обновлении значений [ ] и [ ] при наличии такой возможности улучшения. Ослабление может уменьшить оценку кратчайше-
го пути [ ] и обновить предшественника |
[ ] для вершины . Приведённая ниже |
|
процедура выполняет ослабление ребра ( , ). |
||
Relax( , , ) |
|
|
01 |
if [ ] > [ ] + ( , ) |
|
02 |
then [ ] ← [ ] + ( , ) |
|
03 |
[ ] ← |
|
Пример. На рисунке приведены два примера ослабления ребра. В вершинах указаны оценки кратчайших путей, а рёбра помечены их весами. На рисунке слева оценка кратчайшего пути понижается, на рисунке справа не происходит никаких изменений.
(а) |
5n 2 |
|
- 9n |
(б) |
5n 2 |
|
- 6n |
||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
A |
|
|
|
|
|
|
A |
|
|
|
||
|
5n |
|
A |
|
5n |
|
A |
||||||||
|
2 |
|
- 7n |
|
2 |
|
- 6n |
||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
34 |
Глава II. Алгоритмы для работы с графами |
|
|
Ослабление — единственная операция в алгоритме, которая изменяет оценки кратчайших путей и предшественников, причём каждое ребро ослабляется не более одного раза.
В алгоритме присутствует множество вершин , для которых уже вычислены окончательные веса кратчайших путей к ним из истока . В вычислениях поочерёдно выбирается вершина , которая на данный момент имеет минимальную оценку кратчайшего пути. После добавления этой вершины в множество производится ослабление всех рёбер, исходящих из .
Множество = представляется в виде очереди с приоритетами, в которой вершины с меньшим значением [ ] имеют более высокий приоритет, т.е. множествусопоставляется упорядоченный набор 1, . . . , , состоящий из всех элементов ,
в котором [ ] 6 [ +1] для всех < . Алгоритм работает до тех пор, пока в не
останется вершин.
Алгоритм Дейкстры имеет следующую реализацию в виде псевдокода.
Dijkstra( , , ) |
= , , неотрицательная весовая функция |
{Вход: ориентированный граф |
|
: → R, вершина .} |
|
{Выход: оценка кратчайшего пути [ ] для всех , предшественник [ ] для некоторых .}
01 |
for каждой вершины |
02 |
do [ ] ← ∞ |
03 |
[ ] ↑ |
04 |
[ ] ← 0 |
05 |
← ? |
06 |
← |
07 |
while ̸= ? |
08 |
do ← Extract_Min( ) |
09← { }
10for каждого ребра ( , )
11 do Relax( , , )
Процедура Dijkstra работает следующим образом. В строках 01–04 происходит инициализация величин и : значения [ ] не определены для всех вершин ,
[ ] = 0 и [ ] = ∞ для всех { }. В строках 05–06 инициализируются пустое множество вершин и очередь с приоритетами , которая в начальный момент содержит все вершины из . В алгоритме Дейкстры перед каждой итерацией цикла while (строки 07–11) выполняется тождество = . В строках 08–09 цикла while из множества извлекается вершина с минимальным текущим значением оценки[ ], и затем добавляется в множество . В строках 10–11 ослабляются все рёбра ( , ), исходящие из . Отметим, что количество итераций цикла while в строках 07–11 равно | |.
Результаты работы процедуры Dijkstra могут зависеть от порядка просмотра рёбер в строке 10, а также от порядка извлечения вершин из очереди в строке 08 в
случае, когда в имеется более одной вершины с минимальным текущим значением оценки кратчайшего пути.
Пример. Ниже проиллюстрирован пример работы процедуры Dijkstra с исходной вершиной . В каждой вершине приведена текущая оценка кратчайшего пути к ней. Выделенные рёбра указывают предшественников. Чёрным цветом выделены верши-
§ 6. Алгоритм Дейкстры |
35 |
|
|
ны, добавленные в множество , серым — вершина, которая выбирается в качестве вершины в строке 08, а белым — остальные содержащиеся в множестве =
вершины. На рисунках (а)–(е) проиллюстрированы ситуации, сложившиеся перед очередной итерацией цикла while. На рисунке (ж) приведены окончательные значе-
ния величин и .
(а) |
|
|
|
|
|
|
|
|
|
|
|
|
|
||||||||
|
∞n 4 |
- |
∞n |
1 |
- |
∞n |
|||||||||||||||
|
|
|
|
|
|
|
|
|
|
6 |
|
|
|
|
|
6 |
|||||
|
8 |
|
|
10 |
|
|
|
|
|
|
3 |
9 |
|
|
|
|
|
6 |
|||
|
|
|
|
2 |
|
|
|
|
|
|
4 |
|
|
|
|
||||||
|
n~ |
5 |
|
|
|
|
∞n |
2 |
|
|
|
|
∞n |
||||||||
|
? |
|
|
|
|
|
? |
|
|
|
|
|
|
? |
|||||||
|
|
|
|
- |
|
|
|
|
|
|
|
|
- |
|
|
|
|
|
|
||
|
0 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||
(в) |
|
|
|
|
|
|
|
|
|
|
|
|
|
||||||||
|
|
n |
4 |
- |
|
|
|
n |
1 |
- |
|
|
|
n |
|||||||
|
∞ |
|
8 |
|
|
|
|
14 |
|||||||||||||
|
|
|
|
|
|
|
|
||||||||||||||
|
|
|
|
|
|
|
|
|
|
6 |
|
|
|
|
|
6 |
|||||
|
8 |
|
|
10 |
|
|
|
|
|
|
3 |
9 |
|
|
|
|
6 |
||||
|
|
|
|
2 |
|
|
|
|
|
|
4 |
|
|
|
|
||||||
|
~ |
5 |
|
|
|
|
~ |
2 |
|
|
|
|
n~ |
||||||||
|
? |
|
|
|
|
|
? |
|
|
|
|
|
|
? |
|||||||
|
|
|
|
- |
|
|
|
|
|
|
|
|
- |
|
7 |
|
|
||||
(д) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||
4 |
- |
|
|
|
|
1 |
- |
|
|
|
|
||||||||||
|
n |
|
~ |
|
|
|
~n |
||||||||||||||
|
|
|
|
|
|
|
|
|
|
||||||||||||
|
∞ |
|
|
|
|
|
|
|
|
|
|
|
|
|
9 |
|
|
||||
|
|
|
|
|
|
|
|
|
|
6 |
|
|
|
|
|
6 |
|||||
|
|
|
|
|
|
|
|
|
|
||||||||||||
|
|
|
|
|
|
|
|
||||||||||||||
|
8 |
|
|
10 |
|
|
|
|
|
|
3 |
9 |
|
|
|
|
|
6 |
|||
|
|
|
|
2 |
|
|
|
|
|
|
4 |
|
|
|
|
||||||
|
|
? |
|
|
|
|
|
? |
|
|
|
|
|
|
|
|
? |
|
|
||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||
|
~ |
5 |
- |
~ |
2 |
- |
~ |
||||||||||||||
(ж) |
|
|
|
|
|
|
|
|
|
|
|
|
|||||||||
|
~ |
4 |
- |
|
~ |
1 |
- |
|
~ |
||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||
|
|
|
|
|
|
|
|
|
|
6 |
|
|
|
|
|
6 |
|||||
|
|
|
|
|
|
|
|
|
|
||||||||||||
|
8 |
|
|
10 |
|
|
|
|
|
|
3 |
9 |
|
|
|
|
|
6 |
|||
|
~ |
|
2 |
|
|
|
|
|
|
4 |
|
|
|
|
|||||||
|
|
|
- |
|
|
~ |
|
- |
|
~ |
|||||||||||
|
|
? |
|
|
|
|
|
? |
|
|
|
|
|
|
? |
||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(б) |
|
|
|
|
|
|
|
|
|
|
|
|
|||||||||
|
∞n 4 |
- |
10n |
1 |
- |
∞n |
|||||||||||||||
|
|
|
|
|
|
|
|
|
|
6 |
|
|
|
|
|
|
6 |
||||
|
8 |
|
|
10 |
|
|
|
|
|
3 |
9 |
|
|
|
|
|
|
6 |
|||
|
|
|
|
2 |
|
|
|
|
|
4 |
|
|
|
|
|
||||||
|
~ |
5 |
|
|
|
~n |
2 |
|
|
|
|
∞n |
|||||||||
|
? |
|
|
|
|
? |
|
|
|
|
|
|
? |
||||||||
|
|
|
|
- |
5 |
|
|
|
- |
|
|
|
|
|
|
|
|||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||||
|
|
|
|
|
|
|
|
|
|
|
|||||||||||
|
|
|
|
|
|
|
|
|
|
|
|||||||||||
(г) |
∞n 4 |
- |
8n~ |
1 |
- |
13n |
|||||||||||||||
|
|
|
|
|
|
|
|
|
|
6 |
|
|
|
|
|
||||||
|
|
|
|
|
|
|
|
|
|
|
6 |
||||||||||
|
8 |
|
|
10 |
|
|
|
|
|
3 |
9 |
|
|
|
|
|
|
6 |
|||
|
|
|
|
2 |
|
|
|
|
|
4 |
|
|
|
|
|
||||||
|
|
? |
|
|
|
|
? |
|
|
|
|
|
|
|
|
? |
|
|
|||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||
|
~ |
5 |
- |
|
|
~ |
2 |
- |
~ |
||||||||||||
|
|
|
|
||||||||||||||||||
(е) |
∞~n 4 |
- |
~ |
1 |
- |
~ |
|||||||||||||||
|
|||||||||||||||||||||
|
|
||||||||||||||||||||
|
|
|
|
|
|
|
|
|
|
6 |
|
|
|
|
|
6 |
|||||
|
|
|
|
|
|
|
|
|
|
||||||||||||
|
|
|
|
|
|
|
|
||||||||||||||
|
8 |
|
|
10 |
|
|
|
|
|
3 |
9 |
|
|
|
|
|
|
6 |
|||
|
|
|
|
2 |
|
|
|
|
|
4 |
|
|
|
|
|||||||
|
|
? |
|
|
|
|
? |
|
|
|
|
|
|
|
|
? |
|
|
|||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||
|
~ |
5 |
- |
~ |
2 |
- |
~ |
||||||||||||||
5 2
Свойства алгоритма
Для доказательства корректности работы алгоритма Дейкстры необходимы некоторые свойства оценок кратчайших путей и ослабления рёбер.
Лемма 14. В процессе выполнения процедуры Dijkstra( , , ) для всех вершинвсегда справедливо неравенство ( , ) 6 [ ], а после того как величина [ ] становится равной ( , ), она больше не изменяется.
Доказательство. Докажем справедливость неравенства ( , ) 6 [ ] индукцией по числу применений процедуры Relax.
Непосредственно после инициализации справедливо ( , ) = [ ] = 0 и ( , ) 6 6 [ ] = ∞ для всех { }.
36 |
Глава II. Алгоритмы для работы с графами |
|
|
Пусть перед ослаблением некоторого ребра ( , ) неравенство ( , ) 6 [ ] справедливо для всех . Единственное значение , которое может измениться после ослабления ребра ( , ), — это значение [ ]. Если оно изменяется, то, в силу индукционного предположения, получаем
( , ) + ( , ) 6 [ ] + ( , ) = [ ].
Перед ослаблением ребра ( , ) выполняется неравенство [ ] > [ ]+ ( , ). Следовательно, значение [ ] конечно, а значит, и значение ( , ) тоже конечно. Поэтому в графе существует кратчайший путь из в . Дополнив путь ребром ( , ), получим путь ′ из в с весом ( , ) + ( , ). Вес пути ′ не может быть меньше веса кратчайшего пути из в , откуда заключаем, что
( , ) 6 ( , ) + ( , ) 6 [ ].
Допустим, в некоторый момент становится справедливым равенство [ ] = ( , ). После этого момента значение [ ] не может уменьшиться, т.к. иначе нарушится неравенство [ ] > ( , ). С другой стороны, значение [ ] не может увеличиться, т.к. ослабление ребёр не увеличивает значений . Таким образом, после достижения равенства [ ] = ( , ) значение [ ] не изменяется. 
Следствие 15. Если вершина не достижима из в графе , то в процессе выполнения процедуры Dijkstra( , , ) всегда верно тождество [ ] = ( , ) = ∞.
Доказательство. Следует из леммы 14, поскольку для недостижимой из вершинывсегда справедливо ∞ = ( , ) 6 [ ]. 

Лемма 16. Пусть = , . . . , , — кратчайший в графе путь из к , последним ребром которого является ребро ( , ) , и пусть в процессе выполнения процедуры Dijkstra( , , ) происходит ослабление ребра ( , ). Если в некоторый момент времени до ослабления ребра ( , ) выполняется [ ] = ( , ), то в любой момент времени после ослабления ребра ( , ) выполняется [ ] = ( , ).
Доказательство. Поскольку = , . . . , , — кратчайший путь из к , то, удалив из него ребро ( , ), мы получим путь ′ = , . . . , , который является кратчайшим из к . Отсюда следует тождество
( , ) + ( , ) = ( , ).
Пусть выполняется [ ] = ( , ) в некоторый момент времени до ослабления ребра ( , ). По лемме 14 равенство [ ] = ( , ) остаётся справедливым и впоследствии. Если непосредственно перед данным ослаблением выполняется неравенство [ ] > [ ] + ( , ), то после этой операции оно преобразуется в равенство[ ] = [ ] + ( , ). Если же непосредственно перед ослаблением выполняется неравенство [ ] 6 [ ] + ( , ), то в процессе ослабления ничего не изменится и неравенство сохранится. В любом случае сразу после ослабления ребра ( , ) имеет место соотношение
[ ] 6 [ ] + ( , ) = ( , ) + ( , ) = ( , ).
С другой стороны, по лемме 14 справедливо [ ] > ( , ). Таким образом, сразу после указанного ослабления выполняется равенство [ ] = ( , ), которое впоследствии сохраняется.
§ 6. Алгоритм Дейкстры |
37 |
|
|
Как и при поиске в ширину, окончательные значения функции предшественников однозначно определяют дерево кратчайших путей.
Определение. Пусть — функция предшественников, вычисленная в результате выполнения процедуры Dijkstra( , , ). Определим неориентированный граф= , , где
= { } { | [ ] ↓},
= {( [ ], ) | { }}.
Граф является деревом (доказательство этого факта приведено ниже в теореме 17) и называется деревом кратчайших путей.
Теорема 17 (о корректности алгоритма Дейкстры) . Пусть = , — взвешен-
: → R и
пусть процедура Dijkstra выполняется над графом с исходной вершиной . Тогда справедливы следующие утверждения:
(1)По окончании работы процедуры Dijkstra( , , ) для всех выполняется [ ] = ( , ).
(2)Граф является деревом, состоящим из всех вершин, достижимых из в графе .
(3)Для всех единственный простой путь из в в дереве совпадает с кратчайшим путём из в в графе .
Доказательство. (1) Докажем, что для каждой вершины в момент её добавления в множество выполняется равенство [ ] = ( , ). Допустим, напротив, для некоторой вершины это утверждение неверно. Пусть — первая добавленная в множество вершина, для которой в момент добавления [ ] ̸= ( , ). Ясно, что ̸= , поскольку в момент добавления вершины в множество выполняется[ ] = ( , ) = 0. Из условия ̸= следует, что непосредственно перед добавлением
в множество оно не является пустым.
Вграфе вершина должна быть достижимой из вершины , т.к. в противном случае, в силу следствия 15, всегда выполняется равенство [ ] = ( , ) = ∞, кото-
рое противоречит выбору вершины . Поскольку достижима из , заключаем, что в графе существует кратчайший путь из в . Непосредственно перед добавлением в множество путь соединяет вершину из (вершину ) с вершиной из (вершиной ). Следовательно, можно выбрать первую вершину на пути , принадлежащую , и значит, ей предшествует некоторая вершина (см. рисунок). Тогда путь можно разложить на три составляющие: путь 1, ведущий из в , ребро ( , ) и путь 2, ведущий из в . (Любой из путей 1 и 2 может не содержать ни одного ребра. Путь 2 может возвращаться в множество .)
'$
~ 






2
1 |
|
~ |
n |
|
j |
|
- |
& % |
|||
n






6
38 |
Глава II. Алгоритмы для работы с графами |
|
|
Поскольку вершина попала в множество раньше, чем , а вершина выбрана как первая вершина, после добавления которой в выполняется соотношение[ ] ̸= ( , ), заключаем, что после добавления в множество выполняется равенство [ ] = ( , ). В этот момент (т.е. сразу после добавления в ) происходит ослабление ребра ( , ). Отсюда по лемме 16 следует, что в любой момент времени после ослабления ребра ( , ) справедливо [ ] = ( , ).
Поскольку на кратчайшем пути вершина находится перед вершиной и вес каждого из рёбер неотрицателен, выполняется неравенство ( , ) 6 ( , ). Следовательно, используя лемму 14, получаем, что в момент добавления вершины в множество выполняются соотношения
[ ] = ( , ) 6 ( , ) 6 [ ]. |
(*) |
Однако, поскольку и вершина , и вершина в момент выбора вершины в строке 08 находились в множестве , заключаем, что в этот момент выполняется неравенство [ ] 6 [ ]. Таким образом, оба неравенства в (*) являются равенствами, т.е. в момент добавления вершины в множество выполняется
[ ] = ( , ) = ( , ) = [ ].
Следовательно, [ ] = ( , ), что противоречит выбору вершины .
Итак, для каждой вершины равенство [ ] = ( , ) выполняется в момент её добавления в множество , а значит, в силу леммы 14, оно выполняется и в дальнейшем. Поскольку любая вершина попадает в множество , заключаем, что по окончании работы процедуры Dijkstra( , , ) равенство [ ] = ( , ) выполняется для всех .
(2) Пусть ̸= . Условие выполняется тогда и только тогда, когда значение [ ] становится определённым в процессе работы процедуры Dijkstra( , , ), что, в свою очередь, происходит тогда и только тогда, когда значение [ ] становится конечным после ослабления некоторого ребра ( , ) . Поскольку после окончания работы процедуры Dijkstra( , , ) выполняется [ ] = ( , ), заключаем, чтотогда и только тогда, когда ( , ) < ∞, т.е. достижима из в графе . Заметим также, что при окончательном определении значения [ ] = происходит окончательное присваивание [ ] = [ ] + ( , ), и значит, в силу соотношения[ ] = ( , ) < ∞, отсюда следует, что [ ] = ( , ) < ∞, т.е. , а ребро ( [ ], ) действительно соединяет вершины из .
Таким образом, граф определён корректно и состоит из всех вершин, достижи- мых из в . Тогда — связный граф, поскольку любые две его вершины связаны путями с . Кроме этого, из определения графа видно, что | | = | | − 1. Следовательно, в силу теоремы 4, граф является деревом.
(3) Пусть . По теореме 4 в дереве существует единственный простой путь= 0, . . . , от корня = 0 к вершине = . Как и в случае алгоритма поиска в ширину, можно доказать, что для всех 1 6 6 справедливо свойство −1 = [ ]. Индукцией по длине пути докажем, что этот путь одновременно является кратчайшим путём из в в графе . Если = 0, то путь, состоящий из одной вершины, очевидно, является кратчайшим в . Если же > 0, то ̸= , и значит, определён
предшественник [ ] = . Отсюда, в силу условий = и −1 = [ ], вытекает, что = −1. Ясно, что путь = 0, . . . , −1 является простым путём от к в дереве . Следовательно, в силу индукционного предположения, является крат- чайшим путём из в в графе , и значит, для веса пути выполняется тождество
§ 6. Алгоритм Дейкстры |
39 |
|
|
( ) = ( , ). Тогда вес пути вычисляется как ( ) = ( , ) + ( , ). Заметим, что в момент определения окончательного значения [ ] одновременно определяется окончательное значение [ ] = [ ] + ( , ), причём в этот же момент значение [ ] тоже уже стабилизировалось. Отсюда следует, что ( , ) = ( , ) + ( , ). Тогда( ) = ( , ), откуда заключаем, что — кратчайший путь из в в графе . 
Время работы алгоритма
Инициализация в строках 01–05 требует время, равное (| |). Дальнейшее вре-
мя работы алгоритма зависит от способа реализации очереди с приоритетами. Самое простое — хранить значения [ ] в неупорядоченном массиве с индексами от 1 до | |,
как-то отмечая удалённые значения . Тогда инициализация очереди в строке 06 расходует время, равное (| |). Количество итераций цикла while в строках 07–11 равно | |. Каждая итерация этого цикла начинается с извлечения из очереди вершины, которое осуществляется с помощью процедуры Extract_Min. Один вызов процедуры Extract_Min требует время, равное (| |), поскольку в ней происходит поиск минимума по всему массиву значений . Далее каждое ребро ( , ) обраба-
тывается в цикле for в строках 10–11 ровно по одному разу на протяжении всей работы алгоритма. Поэтому суммарно выполняется | | итераций цикла for, и на каждой
итерации вызывается процедура Relax, исполняемая за время (1). Таким образом, полное время работы алгоритма Дейкстры составляет (| | + | |2 + | |) = (| |2), т.е. время квадратично.
Замечание. Реализация очереди с приоритетами в виде массива предпочтительнее в случае плотного графа, т.е. когда число рёбер достаточно велико. Если граф разреженный, т.е. число его рёбер достаточно мало, быстрее работают реализации очереди с приоритетами в виде бинарной неубывающей пирамиды, или пирамиды Фибоначчи [1,7].
Замечание. В некоторых задачах поиска кратчайшего пути во взвешенном графе веса рёбер могут принимать отрицательные значения. Для решения подобных задач также существуют алгоритмы, с которыми можно ознакомиться в [1,7].
Упражнения
1.Применить алгоритм Дейкстры к следующим ориентированным графам, используя в качестве истока вершину . Указать значения и и пометить вершины, входящие в множество , после каждой итерации цикла while.
(а) |
|
|
|
|
n |
6 |
- |
|
n |
(б) |
|
n |
1 |
- |
|
|
n |
2 |
- |
|
|
n |
|
1 |
- |
|
|
n |
|||||
|
|
|
3 |
* |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||||
|
n |
|
|
|
6 |
|
|
|
6 |
|
|
@ |
@ 8 |
|
|
|
@ |
@ 6 |
|
|
|
|
|
|
|
|
|
||||||
|
H |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||||||||||||
|
|
|
2 |
|
|
1 |
4 |
|
|
7 |
|
4 |
|
|
|
|
6 |
|
|
|
|
2 |
|
|
|
|
4 |
||||||
HH |
|
|
|
2 |
|
|
|
@ |
|
|
|
|
@ |
|
|
|
|
|
|
|
|||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ |
|
|
|
|
|
@ |
|
|
|
|
1 |
|
|
|
|||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||||||||
|
6 |
|
HjH |
|
? |
|
|
|
|
|
? |
|
|
|
? |
|
|
|
|
? |
|
|
|
|
? |
|
|
|
|
|
? |
||
|
|
|
5 |
|
|
|
|
|
|
|
|
|
R@ |
|
|
|
|
R@ |
|
|
|
|
|
|
|
|
|||||||
|
|
|
|
|
|
n |
6 |
- |
|
n |
|
n |
5 |
- |
|
n 1 |
|
|
n 1 |
- |
|
n |
|||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||||||||||||||||
|
|
|
|
3 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||
2.Привести пример ориентированного графа, содержащего рёбра с отрицательным весом, для которого алгоритм Дейкстры даёт неправильные ответы при поиске кратчайших путей.
40 |
Глава II. Алгоритмы для работы с графами |
|
|
3.Пусть во взвешенном ориентированном графе веса рёбер, выходящих из некоторого истока , могут быть отрицательными, веса всех других рёбер неотрицательные, и не содержит циклов отрицательного веса. Доказать, что в таком графе алгоритм Дейкстры корректно находит кратчайшие пути из истока .
§7. Алгоритм Крускала
При разработке электронных схем часто возникает необходимость электрически связать несколько компонентов в одну схему, соединяя контакты компонентов попарно проводом. Обычно желательно получить компоновку, использующую минимальное количество провода.
Эта задача моделируется на связном неориентированном графе = , с весовой функцией : → R, где — множество контактов, — множество возможных соединений между парами контактов, а вес ( , ) ребра ( , ) интерпретируется как количество необходимого провода для соединения и .
Ясно, что оптимальная компоновка не может содержать циклов, поскольку удаление ребра из цикла снижает расход провода без потери связности схемы. Таким об-
разом, математическая задача состоит в поиске ациклического подмножества , которое соединяет все вершины и чей общий вес
∑
( ) = ( , )
( , )
минимален. Поскольку множество ациклическое и связывает все вершины , граф, должен быть деревом, которое называют остовным деревом графа , а задачу
поиска с минимальным весом именуют задачей поиска минимального остовного дерева (minimum-spanning-tree problem).
Пример. На рисунке показан пример взвешенного связного неориентированного графа и его минимального остовного дерева. На рёбрах указан их вес, а рёбра ми-
нимального остовного дерева выделены цветом. Общий вес данного дерева равен 37. Приведённое дерево не единственное: удалив ребро ( , ) и заменив его ребром ( , ), мы получим другое остовное дерево с тем же весом 37.
|
|
|
n |
8 |
n |
7 |
|
|
n |
|
|
||||
|
4 |
|
|
|
|
|
|
|
|
|
|
|
|
||
|
|
|
|
|
|
@ |
|
|
@ |
9 |
n |
||||
n |
|
|
7 n6 |
|
|
@ |
|
|
|
@ |
|||||
|
|
|
|
|
|
2 |
|
|
|
|
|
|
|||
|
11 |
|
|
|
|
|
n |
4@ |
14 |
|
|||||
|
@ |
n |
@ |
@ |
|
@ |
n |
|
|
||||||
|
8@ |
|
|
|
|
@ 10 |
|
||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
|
|
|
|
2 |
|
|
|
|
|
Убедимся в том, что задача нахождения минимального остовного дерева в связном неориентированном графе разрешима.
Предложение 18. Для любого взвешенного связного неориентированного графа= , существует минимальное остовное дерево.
