Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Дискретная математика и теория алгоритмов. Учебное пособие

.pdf
Скачиваний:
0
Добавлен:
12.08.2026
Размер:
1 Мб
Скачать

§ 4. Поиск в ширину

21

 

 

Доказательство. Непосредственно после инициализации все вершины { } имеют белый цвет, и поэтому [ ] = ∞ > ( , ). Кроме этого, для вершины справедливо [ ] = 0 = ( , ).

Из кода процедуры BFS видно, что значение [ ] может измениться только у белой вершины , причём после такого изменения вершина помещается операцией inject в очередь, окрашивается в серый цвет и никогда уже не станет белой, и значит, после этого значение [ ] больше не изменяется.

Таким образом, достаточно доказать утверждение леммы для вершин , у которых значение [ ] меняется с бесконечного на конечное. Доказательство проведём индукцией по числу применений операции inject.

Впервые операция inject используется в строке 09 для исходной вершины . После её применения, как было установлено выше, неравенство [ ] > ( , ) выполняется для всех .

Пусть после -го применения операции inject справедливо [ ] > ( , ) для всех. Рассмотрим ( +1)-е применение операции inject (строка 17), которое помещает некоторую вершину в очередь. В этом случае вершина смежна вершине , цвет которой отличен от белого. Следовательно, значение [ ] уже стабилизировалось, и, в силу индукционного предположения, справедливо [ ] > ( , ). Тогда в силу присвоения в строке 15 и леммы 5 получаем

[ ] = [ ] + 1 > ( , ) + 1 > ( , ).

Следующая лемма показывает, что в любой момент времени в очереди находится не более двух различных значений расстояния .

Лемма 7. Предположим, что в процессе выполнения процедуры BFS( , ) очередь находится в состоянии = 1, 2, . . . , . Тогда [ ] 6 [ 1] + 1 и [ ] 6 [ +1] для всех 1 6 6 − 1.

Доказательство. Докажем утверждение леммы индукцией по числу операций с очередью. Когда очередь пуста или состоит из одной исходной вершины , утверждение очевидно.

Если из очереди извлекается её голова 1, новой головой очереди становится вершина 2. В силу индукционного предположения, [ 1] 6 [ 2]. Тогда [ ] 6 [ 1]+1 6 6 [ 2] + 1, а все остальные неравенства не изменяются.

Если в очередь помещается вершина после исполнения строки 17, то становится вершиной +1 в хвосте очереди. Следовательно, вершина смежна некоторой вершине , которая в текущей итерации цикла while была удалена из очереди. Пусть непосредственно перед удалением из очереди её состояние имело вид, 1, 2, . . . , для некоторого 6 . Следовательно, вершины +1, . . . , тоже бы- ли добавлены в очередь в текущей итерации цикла while, и значит, +1, . . . , тоже смежны вершине . Если = 0, то [ 1] = · · · = [ +1] = [ ] + 1 и утверждение леммы очевидно. Если же > 1, то, в силу индукционного предположения для состояния очереди , 1, 2, . . . , , справедливы неравенства [ ] 6 [ 1] и [ ] 6 [ ] + 1. Тогда [ +1] = [ ] = [ ] + 1 6 [ 1] + 1. Кроме этого, [ ] 6 [ ] + 1 = [ +1] = = · · · = [ +1], а все остальные неравенства не изменяются.

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

22

Глава II. Алгоритмы для работы с графами

 

 

Следствие 8. Предположим, что в процессе выполнения процедуры BFS( , ) вершины и помещаются в очередь , причём попадает в очередь до . Тогда в момент помещения в очередь выполняется неравенство [ ] 6 [ ].

Доказательство. Вытекает из леммы 7 и того факта, что в процессе выполнения процедуры BFS каждая вершина получает конечное значение [ ] не более одного раза.

Дерево поиска в ширину однозначно определяется функцией предшественников.

Определение. Пусть — функция предшественников, вычисленная в результате применения процедуры BFS( , ) к графу = , с исходной вершиной . Определим неориентированный граф = , , где

= { } { | [ ] ↓},

= {( [ ], ) | { }}.

Граф является деревом (доказательство этого факта приведено ниже в теореме 9) и называется деревом поиска в ширину.

Теорема 9 (о корректности поиска в ширину). Пусть = , — ориентированный или неориентированный граф и пусть процедура BFS выполняется над графом

с исходной вершиной . Тогда справедливы следующие утверждения:

(1)По окончании работы BFS( , ) для всех выполняется [ ] = ( , ).

(2)В процессе работы BFS( , ) открываются все вершины, достижимые из .

(3)Граф является деревом, состоящим из всех вершин, достижимых из в графе .

(4)Для всех в дереве имеется единственный простой путь из в , который одновременно является кратчайшим путём из в в графе .

Доказательство. (1) Допустим, напротив, существуют вершины такие, что[ ] ̸= ( , ). Среди всех таких вершин выберем вершину с минимальной длиной( , ). Очевидно, что ̸= . В силу леммы 6, имеет место [ ] > ( , ). Следовательно, в силу нашего предположения, [ ] > ( , ). Тогда вершина должна быть достижима из , так как иначе ( , ) = ∞ > [ ]. Выберем в графе какой-нибудь кратчайший путь из в . Так как ̸= , на этом пути есть вершина , непосредственно предшествующая вершине . Следовательно, ( , ) = ( , ) + 1. Таким образом,( , ) < ( , ) и, значит, в силу выбора вершины , заключаем, что [ ] = ( , ). Объединяя найденные соотношения, получаем

[ ] > ( , ) = ( , ) + 1 = [ ] + 1.

(*)

Ясно, что вершина тоже достижима из . Следовательно, значение ( , ) конечно, и значит, [ ] тоже конечно. Из кода процедуры BFS видно, что если [ ] присваивается конечное значение, то попадает в очередь . Следовательно, наступит момент, когда будет удалена из очереди (строка 11). В этот момент вершинаможет быть белой, серой или чёрной. Покажем, что в любом из этих трёх случаев получается противоречие с неравенством (*). Если белая, то в строке 15 выполняется присваивание [ ] = [ ] + 1, противоречащее (*). Если чёрная, то она уже

§ 4. Поиск в ширину

23

 

 

удалена из очереди и, в силу следствия 8, [ ] 6 [ ], что опять противоречит (*). Если серая, то она была покрашена в этот цвет при удалении из очереди некоторой вершины , которая была удалена раньше вершины и для которой выполняется[ ] = [ ]+1. Однако из следствия 8 вытекает, что [ ] 6 [ ], поэтому [ ] 6 [ ]+1, что тоже противоречит (*).

(2) Допустим, существует достижимая из вершина , которая не открывается процедурой BFS( , ). Тогда [ ] = ∞, но при этом значение ( , ) конечно, что противоречит доказанному выше свойству [ ] = ( , ).

(3) Заметим, что для вершины ̸= условие равносильно тому, что значение [ ] становится определённым в строке 16 процедуры BFS, что, в свою очередь, происходит тогда и только тогда, когда значение [ ] становится конечным в строке 15. Поскольку [ ] = ( , ), заключаем, что тогда и только тогда, когда( , ) < ∞, т.е. достижима из в графе . Также отметим, что если [ ] = , то[ ] = [ ] + 1, и следовательно, из условия [ ] = ( , ) < ∞ вытекает соотношение[ ] = ( , ) < ∞, т.е. , а ребро ( [ ], ) действительно соединяет вершины из .

Таким образом, граф определён корректно и состоит из всех вершин, достижи- мых из в . Тогда — связный граф, поскольку любые две его вершины связаны путями с . Кроме этого, из определения графа следует, что | | = | | − 1. Следовательно, в силу теоремы 4, граф является деревом.

(4) Пусть . Поскольку является деревом, в силу теоремы 4, заключаем, что в существует единственный простой путь = 0, . . . , от корня = 0 к вершине = . Докажем, что для всех 1 6 6 справедливо свойство −1 = [ ] (т.е. случай [ −1] = невозможен). Действительно, для = 1 это свойство справедливо, поскольку [ ] не определено. Далее, рассуждая по индукции, допустим, что для фиксированного > 1 справедливо свойство −1 = [ ]. Если тождество= [ +1] неверно, то [ ] = +1, откуда следует, что −1 = +1, а это противоре- чит простоте пути . Следовательно, = [ +1], что и требовалось.

Теперь индукцией по длине пути докажем, что этот путь одновременно является кратчайшим путём из в в графе . Если = 0, то путь, состоящий из одной вершины , очевидно, является кратчайшим в . Если же > 0, то ̸= , и

значит, определено значение [ ] = . Отсюда, в силу условий = и −1 = [ ], вытекает, что = −1. Ясно, что путь = 0, . . . , −1 является простым путём от к в дереве . Следовательно, в силу индукционного предположения, яв- ляется кратчайшим путём из в в графе , и значит, длина пути совпадает со значением ( , ). Тогда длина пути равна ( , ) + 1. Заметим, что по построению[ ] = [ ] + 1, откуда следует, что ( , ) = ( , ) + 1. Тогда длина пути равна( , ), т.е. — кратчайший путь из в в графе .

Время работы алгоритма

Инициализация в строках 01–07 расходует одно и то же постоянное количество операций на каждую из вершин. Поэтому общее время выполнения инициализации

равно (| |). После инициализации ни одна вершина не окрашивается в белый цвет,

поэтому проверка в строке 13 гарантирует, что каждая вершина вносится в очередь не более одного раза, а следовательно, и удаляется из очереди не более одного ра-

за. Операции внесения в очередь и удаления из неё требуют (1) времени, так что общее количество операций с очередью составляет (| |). Все оставшиеся операции производятся в цикле while, внутри которого для каждой вершины , извлекаемой

24

Глава II. Алгоритмы для работы с графами

 

 

из очереди, сканируется список всех выходящих из рёбер, для каждого из которых осуществляется (1) операций. Если граф ориентированный, то ребро в цикле

просматривается один раз; если неориентированный — то два раза. Поскольку суммарное количество рёбер равно | |, общее время выполнения всех итераций цикла

while равно (| |). Таким образом, общее время работы процедуры BFS составляет(| |+| |), т.е. время поиска в ширину линейно зависит от размера входного графа.

Упражнения

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

1n -

2n

 

3n

 

 

 

 

 

 

 

 

 

 

 

 

 

 

n

 

 

n

 

 

n

 

 

 

 

 

 

?

 

 

?

 

?

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

4

 

 

5

 

6

 

 

 

 

 

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

n

n

 

 

n

 

n

n

n

 

n

 

 

 

n

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

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

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

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

4.Используя процедуру BFS, разработать алгоритм нахождения всех связных компонентов неориентированного графа.

§5. Поиск в глубину

Обход графа методом поиска в глубину (depth-first search) часто используется в качестве подпрограммы в других алгоритмах. Так же как и обход в ширину, алгоритм поиска в глубину даёт важную информацию о структуре графа. Основное отличие поиска в глубину от поиска в ширину заключается в том, что множество открытых к данному моменту вершин организовано не в виде очереди, как это было сделано в

§ 5. Поиск в глубину

25

 

 

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

Описание алгоритма

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

кидает вершину и возвращается в ту, из которой была открыта . Этот процесс

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

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

ваны все выходящие из неё рёбра, становится чёрной. Цвет вершины хранится в переменной [ ].

Алгоритм также проставляет в вершинах метки времени. Каждая вершина имеет две такие метки. В первой метке [ ] указывается время открытия вершины . Вторая метка [ ] фиксирует время завершения исследования выходящих из рёбер. Метки времени представляют собой целые числа от 1 до 2·| |. Для проставления меток времени используется глобальная переменная .

Как и в случае поиска в ширину, когда вершина открывается в процессе сканирования вершин, смежных с уже открытой вершиной , алгоритм поиска в глубину объявляет предшественником вершины . Предшественник вершины хранится в

переменной [ ], а рёбра вида ( [ ], ) образуют лес поиска, который может состоять

из нескольких деревьев поиска.

Представленная ниже процедура поиска в глубину DFS работает как для ориентированных, так и для неориентированных графов.

DFS( )

{Вход: граф = , .} {Выход: время открытия [ ] и время завершения [ ] для всех , предшественник [ ] для некоторых .}

01

for каждой вершины

02

do [ ] ← white

03

[ ] ↑

04

← 0

05

for каждой вершины

06

do if [ ] = white

07

then DFS_Visit( )

DFS_Visit( )

01

[ ] ← gray

02

← + 1

03

[ ] ←

04

for каждого ребра ( , )

05

do if [ ] = white

06

then [ ] ←

DFS_Visit

26

Глава II. Алгоритмы для работы с графами

 

 

07

DFS_Visit( )

08

[ ] ← black

09← + 1

10[ ] ←

Процедура DFS работает следующим образом. В строках 01–03 все вершины окрашиваются в белый цвет, а их предшественники объявляются неопределёнными. В строке 04 выполняется сброс глобального счётчика времени. В строках 05–07

поочерёдно проверяются все вершины из , и, когда обнаруживается белая вершина, она обрабатывается с помощью процедуры DFS_Visit, которая вызывается

встроке 07, при этом вершина становится корнем нового дерева из леса поиска.

Вмомент вызова процедуры DFS_Visit( ) вершина имеет белый цвет. В строках 01–03 она окрашивается в серый цвет, глобальная переменная увеличивается на единицу, и новое значение фиксируется как время открытия [ ] вершины . В строках 04–07 исследуются все вершины , смежные с , и, если вершина белая, её предшественником объявляется вершина , и выполняется рекурсивное посещение вершины . Наконец, после того как исследованы все вершины, смежные с , в строках 08–10 вершина окрашивается в чёрный цвет, переменная увеличивается

на единицу и записывается время завершения [ ] работы с вершиной .

Результаты поиска в глубину могут зависеть от порядка просмотра вершин в строке 05 процедуры DFS, а также от порядка посещения смежных вершин в строке 04 процедуры DFS_Visit.

Пример. Ниже проиллюстрирована работа процедуры DFS на примере шестиэлементного ориентированного графа. В вершинах указаны метки времени в формате открытие/завершение. Рёбра, исследованные процедурой в строке 04, либо выделяются серым цветом (если это рёбра деревьев), либо помечены буквами F (прямые рёбра), B (обратные рёбра) или C (перекрёстные рёбра). (Разметка рёбер не входит в функции процедуры DFS. Определение типов рёбер будет приведено позже.)

(а) 1/

 

-

 

 

 

 

 

 

 

 

 

(б) 1/

 

-

2/

 

 

 

 

 

 

~~

 

 

 

 

 

 

 

~~ ~~

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

?

 

 

 

 

 

 

?

?

 

 

 

 

 

?

 

 

 

 

 

 

?

?

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

(в) 1/

 

-

2/

 

 

 

 

 

(г) 1/

 

-

2/

 

 

 

 

 

 

~~ ~~

 

 

 

 

 

~~ ~~

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

3/

 

 

 

 

 

 

 

4/

 

 

 

3/

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

~~

 

 

~~ ~~

 

 

 

 

?

 

 

 

 

 

 

?

?

 

 

 

 

 

?

 

 

 

 

 

 

?

?

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

(д) 1/

 

-

2/

 

 

 

 

 

(е) 1/

 

-

2/

 

 

 

 

 

 

~~B ~~

 

 

 

 

 

~~B ~~

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

4/

 

 

3/

 

 

 

 

 

 

 

 

 

 

 

 

3/

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

~~ ~~

 

 

~~ ~~

 

 

 

 

?

 

 

 

 

 

 

?

?

 

 

 

 

 

?

 

 

 

 

 

 

?

?

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

§ 5. Поиск в глубину

27

 

 

(ж) 1/

 

-

2/

 

 

 

 

 

 

~~B ~~

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

~~ ~~

 

 

 

 

?

 

 

 

?

?

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

(и) 1/

 

-

 

 

 

 

 

 

 

 

~~B ~~

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

F

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

~~ ~~

 

 

 

 

?

 

 

 

?

?

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

(л)

 

 

 

 

-

 

 

 

9/

 

 

~~B ~~ ~~

 

 

 

 

 

 

 

 

 

 

 

 

 

F

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

~~ ~~

?

 

 

 

?

 

 

 

?

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

(з) 1/

 

-

 

 

 

 

 

 

 

 

 

~~B ~~

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

~~ ~~

 

 

 

 

 

?

 

 

 

 

?

?

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

(к)

 

 

-

 

 

 

 

 

 

 

 

 

 

 

 

 

 

~

~B

~~

 

 

 

 

 

 

 

 

 

 

F

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

~~ ~~

 

 

 

 

?

 

 

 

 

?

?

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

(м)

 

 

 

 

-

 

 

 

9/

 

 

 

~~B ~~ ~~

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

F

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

C

 

 

 

 

~~ ~~

?

 

 

 

 

?

 

 

 

 

?

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

(н)

 

 

-

 

 

9/

 

 

~~B ~~ ~~

 

 

 

 

 

 

 

 

 

 

 

F

 

 

 

 

 

 

 

~~

~~ ~~

 

 

 

 

 

 

 

?

 

 

 

 

?

 

? C

 

 

 

 

 

 

 

 

10/

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

(о)

 

 

 

-

 

 

 

9/

 

 

~~B ~~ ~~

 

 

 

 

 

 

 

 

 

 

 

 

F

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

B

~~

~~ ~~

 

 

 

 

 

 

 

 

 

?

 

 

 

 

?

 

? C

 

 

 

 

 

 

 

 

10/

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

(п)

 

 

-

 

 

 

9/

 

 

(р)

 

 

-

 

 

 

 

 

 

 

 

~~B ~~ ~~

~~B ~~ ~~

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

F

 

 

 

 

 

 

 

 

 

 

F

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

C

 

 

B

 

 

 

 

 

C

 

 

B

 

 

 

 

 

 

 

 

 

~~

~~ ~~

~~

~~ ~~

 

 

?

 

 

 

 

 

?

 

 

 

 

?

 

 

 

 

?

 

 

 

 

 

 

?

 

 

 

 

 

 

 

?

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Свойства алгоритма

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

Определение. Пусть — функция предшественников, вычисленная в результате применения процедуры DFS( ) к графу = , . Определим неориентированный граф = , , где

= {( [ ], ) | и [ ] ↓}.

Граф является лесом (доказательство этого факта приведено ниже в теореме 11), называется лесом поиска в глубину и состоит из нескольких деревьев поиска в глубину. Вершины , для которых не определено значение [ ], будем называть

корнями деревьев поиска в глубину.

Лемма 10. Пусть = , — ориентированный или неориентированный граф,, и [ ] 6 [ ] < [ ]. Тогда в графе существует путь из вершины в вершину .

[ ]. Если

28 Глава II. Алгоритмы для работы с графами

Доказательство. Докажем утверждение леммы индукцией по значению[ ] = [ ], то = и утверждение очевидно.

Пусть [ ] > [ ]. Поскольку [ ] < [ ] < [ ], заключаем, что вершина открывается в процессе исполнения процедуры DFS_Visit( ). Следовательно, в процессе исполнения DFS_Visit( ) для некоторой вершины происходит рекурсивный вы- зов процедуры DFS_Visit( ), при исполнении которой вершина открывается как смежная с . Таким образом, по построению [ ] = и ребро ( , ) добавляется

в граф . Ясно, что [ ] 6 [ ] < [ ]. Тогда, в силу индукционного предположения, в графе существует путь из в . Дополнив путь ребром ( , ) ,

получаем искомый путь из в .

Теорема 11 (о корректности поиска в глубину) . Пусть = , — ориентированный или неориентированный граф и пусть процедура DFS выполняется над графом. Тогда справедливы следующие утверждения:

(1)В процессе работы DFS( ) открываются все вершины графа .

(2)Граф является лесом, состоящим из нескольких деревьев.

Доказательство. (1) Цикл for в строках 05–07 процедуры DFS просматривает все вершины , и если вершина белая, то она открывается вызовом процедуры

DFS_Visit( ), а если не белая, то уже была открыта ранее. Таким образом, к моменту окончания работы DFS( ) все вершины графа будут открыты.

(2) Пусть 1, . . . , — набор всех вершин из , которые при проверке в строке 06 процедуры DFS оказались белыми, при этом будем считать, что при < вершина просматривается процедурой раньше, чем . Процедура DFS_Visit( ) не изменяет значение [ ], поэтому к моменту окончания поиска в глубину значе-

ние [ ] не определено для всех 1 6 6 . Все остальные вершины, т.е. вершины

{ 1, . . . , }, открываются рекурсивным вызовом DFS_Visit( ) в строке 07 процедуры DFS_Visit, а значит, в строке 06 для них определяется предшественник

[ ].

Для каждого 1 6 6 обозначим через множество вершин , которые открываются в процессе работы процедуры DFS_Visit( ), т.е. [ ] 6 [ ] < [ ]. Заметим, что для < в момент запуска процедуры DFS_Visit( ) все вершины из уже окрашены в чёрный цвет, а в процессе работы DFS_Visit( ) открываются только белые вершины. Следовательно, ∩ = ? для всех ̸= . Таким образом, { 1, . . . , } является разбиением на непересекающиеся подмножества, причём , 1 6 6 .

Для каждого 1 6 6 положим = {( [ ], ) | { }}. Заметим, что для любой вершины { } в момент определения её предшественника [ ] вершина= [ ] должна быть серой. Поскольку в этот момент все вершины из 1 · · · −1 уже окрашены в чёрный цвет, а все вершины из +1 · · · пока остаются белыми, заключаем, что . Таким образом, замкнуто относительно предшественников, и значит, × .

Обозначим = , , 1 6 6 . Мы установили, что граф разбивается на попарно несвязанные графы 1, . . . , . Докажем, что для всех 1 6 6 граф связный. Для этого достаточно показать, что для любой вершины в графе существует путь из в . Из неравенства [ ] 6 [ ] < [ ] по лемме 10 следует, что в графе существует путь из в . Поскольку и замкнуто относительно предшественников, заключаем, что данный путь полностью содержится в графе .

Лемма 12.

 

§ 5. Поиск в глубину

 

29

 

 

 

 

Итак, для всех 1 6

6 граф связный и при этом

| |

= | | − 1. Следо-

вательно, по теореме 4 графы 1, . . . , являются деревьями с корнями 1, . . . , соответственно, а их объединение, т.е. граф , — лесом.

Тот факт, что граф является лесом, позволяет нам говорить о потомках и предках в деревьях данного леса.

Пусть — лес поиска, полученный в результате применения процедуры DFS к ориентированному или неориентированному графу = , , и пусть, , ̸= . Вершина является потомком вершины в лесу тогда и только тогда, когда вершина была серой в момент открытия вершины .

Доказательство. (= ) Поскольку , заключаем, что в одном из деревьев поиска с корнем существует путь 0, . . . , такой, что 0 = , = и = [ +1] для всех < . Достаточно показать, что в момент открытия вершины все вер-

шины 0, . . . , −1 окрашены в серый цвет. Докажем это утверждение индукцией по значению , изменяющемуся от − 1 до 1. Очевидно, в момент открытия вершины

её предшественник −1 должен иметь серый цвет. Допустим теперь, что в момент открытия вершина +1 имеет серый цвет. Из условия = [ +1] следует, что+1 была открыта при исполнении строки 07 процедуры DFS_Visit( ), при этом произошёл рекурсивный вызов процедуры DFS_Visit( +1). Поскольку в рассматриваемый момент вершина +1 всё ещё серая, процедура DFS_Visit( +1) ещё не завершила свою работу, и значит, процедура DFS_Visit( ) ещё не перешла к ис-

полнению строки 08. Таким образом, вершина в рассматриваемый момент тоже серая.

( =) Пусть в момент открытия вершины вершина имеет серый цвет. Следовательно, ранее была вызвана процедура DFS_Visit( ), которая в момент открытия вершины ещё не закончила свою работу. Отсюда следует, что [ ] < [ ] < [ ]. В силу леммы 10 в графе найдётся путь из в . Тогда путь полностью содержится в одном из деревьев поиска с некоторым корнем . В этом дереве существует единственный путь из в , дополнив который путём , мы получим путь из в , показывающий, что является потомком в данном дереве.

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

вершины в виде открывающейся скобки “ ( ”, а завершение — в виде закрывающейся скобки “ )”, то хронологический список открытий и завершений образует корректное выражение в смысле сбалансированности скобок.

Пример. Пусть результат поиска в глубину имеет вид, изображённый на рисунке.

~~ ~~ ~~ ~~

 

 

 

 

 

6

 

 

 

6

 

 

 

 

 

 

B

 

 

F

C

 

 

 

B

 

 

 

 

 

 

~

~

~~ ~~ ~~

?

?

 

?

 

 

 

 

 

 

 

 

 

 

 

 

 

 

C

 

 

C

 

C

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Тогда соответствующее ему скобочное выражение имеет вид

( ) ( )

( )

( ( ) )( ) ( )( ) .

30

Глава II. Алгоритмы для работы с графами

 

 

Теорема 13 (о скобках). Пусть процедура DFS применяется к ориентированному или неориентированному графу = , . Тогда для любых различных вершин

, выполняется ровно одно из следующих трёх утверждений:

(1)Отрезки [ [ ], [ ]] и [ [ ], [ ]] не пересекаются, и ни не является потомкомв лесу поиска , ни не является потомком .

(2)Отрезок [ [ ], [ ]] полностью содержится в отрезке [ [ ], [ ]], и является потомком в лесу поиска .

(3)Отрезок [ [ ], [ ]] полностью содержится в отрезке [ [ ], [ ]], и является потомком в лесу поиска .

Доказательство. Из условия ̸= следует, что [ ] < [ ] или [ ] > [ ]. Рассмотрим случай [ ] < [ ], в котором имеется два подслучая, в зависимости от того, справедливо неравенство [ ] < [ ] или нет. Если [ ] < [ ], то вершина была открыта, когда вершина была окрашена в серый цвет. Отсюда по лемме 12 заключаем, что является потомком вершины в лесу . Кроме этого, поскольку вершина открыта позже, чем , перед тем как вернуться для завершения поиска к вершине , процедурой DFS будут исследованы все выходящие из рёбра. В таком случае отрезок [ [ ], [ ]] полностью содержится в отрезке [ [ ], [ ]], т.е. выполняется утверждение (3). Если же [ ] < [ ], то отрезки [ [ ], [ ]] и [ [ ], [ ]] не пересекаются, а значит, когда открывается одна их вершин или , другая имеет

белый или чёрный цвет. Следовательно, в силу леммы 12, ни одна из данных вершин не является потомком другой, т.е. выполняется утверждение (1).

Случай [ ] > [ ] рассматривается аналогично. Здесь будет справедливо либо утверждение (1), либо утверждение (2).

Поиск в глубину можно использовать для классификации рёбер входного графа.

Определение. Пусть — лес поиска, полученный в результате применения процедуры DFS к ориентированному или неориентированному графу = , . Опре-

делим следующие четыре типа рёбер графа :

(а) Рёбра деревьев — это рёбра графа .

(б)Обратные рёбра — это рёбра ( , ) , соединяющие вершину с её предкомв дереве поиска. Рёбра-петли, которые могут встречаться в ориентированных графах, считаются обратными рёбрами.

(в)Прямые рёбра — это рёбра ( , ) , не являющиеся рёбрами деревьев и соединяющие вершину с её потомком в дереве поиска.

(г)Перекрёстные рёбра — все остальные рёбра. Они могут соединять вершины из разных деревьев поиска или вершины одного и того же дерева поиска, когда ни одна из вершин не является предком другой.

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

дважды: в виде ( , ) и ( , ). В таком случае, когда ребро удовлетворяет нескольким

категориям из списка (а)–(г), оно классифицируется в соответствии с первой категорией в списке, применимой для данного ребра. Приняв данное соглашение, можно

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]