![]() |
Главная Случайная страница Контакты | Мы поможем в написании вашей работы! | |
|
В этом параграфе рассматривается один из методов обхода всех вершин и ребер графа. Этот метод, именуемый поиском в глубину (сокращенно ПГ), послужил основой для разработки ряда быстрых алгоритмов на графах. Один из таких алгоритмов — алгоритм выделения двусвязных компонент графа — приводится в § 74. Дадим вначале некоторые определения. Ориентирований граф D — (V, A) назовем ориентированным деревом корнем r € V, если каждая его вершина достижима из и основание графа D — граф Db — является деревом. В тех случаях, когда недоразумение исключено, ориентированное дерево с корнем r будем называть просто деревом.
Пусть G — неориентированный связный граф, В провесе поиска в глубину вершинам графа G присваиваютcя номера (ПГ-номера), а его ребра помечаются. В начале ребра не помечены, вершины не имеют ПГ-номеров. Начинаем с произвольной вершины v0. Присваиваем ей ПГ-номер ПГ(v0)=1 и выбираем произвольное ребро v0w Ребро v0w помечается как «прямое», а вершина w включает (из v0) ПГ-номер ПГ(w)=2. После этого переводим в вершину w. Пусть в результате выполнения нескольких шагов этого процесса пришли в вершину х, и Пусть k — последний присвоенный ПГ-номер. Далее действуем в зависимости от ситуации следующим образом.
1. Имеется непомеченное ребро ху. Если у вершины уже есть ПГ-номер, то ребро ху помечаем как «обратное» продолжаем поиск непомеченного ребра, инцидентного вершине х. Если же вершина у ПГ-номера не имеет, то полагаем ПГ(y) = k + 1, ребро ху помечаем как «прямое»: переходим в вершину у. Вершина у считается получившей свой ПГ-номер из вершины х. На следующем шаге будем просматривать ребра, инцидентные вершине у.
2. Все ребра, инцидентные вершине х, помечены. В этом случае возвращаемся в вершину, из которой х получила свой ПГ-номер.
Процесс закончится, когда все ребра будут помечены: произойдет возвращение в вершину v0.
Описанный процесс можно реализовать так, чтобы ремя работы соответствующего алгоритма составляло (/ EG / + / G / ).
Такой алгоритм (алгоритм A1) мы сейчас рассмотрим. Пусть граф G задан списками смежности, т. е. Nv — список вершин, инцидентных вершине v, и v0 — исходная вершина, с которой начинается поиск. В процессе работы алгоритма каждая вершина графа ровно один раз включается в список Q и исключается из него. Вершина включается в этот список сразу после получения ПГ-номера, исключается, как только произойдет возвращение из этой вершины. Включение и исключение вершин производятся всегда с конца списка, т. е. Q — стек. Результат работы алгоритма — четыре списка ПГ, F, Т и В: ПГ(v)— ПГ-номер вершины v; F(v)— имявершины, из которой вершина v получила свой ПГ-номер; Т и В — соответственно списки ориентированных «прямых» и «обратных» ребер графа G. Эти ребра получают ориентацию в процессе работы алгоритма a1. Именно, если ребро ху помечается из вершины х как «прямое», то в Т заносится дуга (х, у), а если — как «обратное», то эта дуга заносится в В.
![]() |
1 ПГ (v):=1, Q(1):= v0, F(vo):=0, T:=¢, B:=¢, k:=1,р:=1 [ k — последний присвоенный ПГ-номер, р — указатель конца стека Q, т. е. Q(p)— имя последней вершины стека Q ].
2. v:= Q(p) [ v — исследуемая вершина].
3. Просматривая список Nv, найти такую вершину w, что ребро vw не помечено, и перейти к п. 4. Если таких вершин нет, то перейти к п. 5.
4. Если вершина w имеет ПГ-номер, то пометить ребро vw как «обратное» и занести дугу (v, w) в список В. Перейти к п. 3 и продолжить просмотр списка Nv. Иначе k:=k + 1, ПГ (w):=k, F(w):=v, ребро vw пометить как «прямое» и дугу (v, w) занести в список T, р:=р+ 1, Q(p):=w [вершина w получила ПГ-номер и занесена встек Q ]. Перейти к п. 2.
5. р:= р — 1 [вершина v вычеркнута из Q ]. Если р = 0, то конец. Иначе перейти к п. 2.
Корректность алгоритма очевидна. Оценим его трудоемкость. Каждое включение и исключение вершины из стека Q выполняется за время O (1). Поэтому для всей работы, связанной с изменением стека Q, достаточно времени O (|G|). Каждое выполнение п. 4 требует O (1) времени, и для каждой вершины v € VG этот пункт выполняется deg v раз. Поэтому затраты на его выполнение в
целом составят O (∑deg v) = О (| EG|). Суммарное время выполнения п. 3 также составит O( | EG|), если позаботиться о том, чтобы каждая вершина списка Nv просматривалась только один раз при всех выполнениях данного пункта. Этого легко добиться, если, например, ввести такую новую функцию (массив) t, что t(v) —номер первой непросмотренной вершины в списке Nv. Тогда следующий просмотр п. 3 следует начинать с вершины z = Nv(t(v)).
Итак, трудоемкость алгоритма A1 составляет O( | EG|+ | G|). Ясно, что это время является наилучшим возможным по порядку, так как каждая вершина и каждое ребро графа G должны быть просмотрены хотя бы один раз.
Легко видеть, что требуемый для реализации алгоритма A1 объем памяти также составляет O( | EG|+ | G|).
На рис. 73.1 слева изображены граф G и списки смежности, которыми он задан. Справа представлены результаты применения к этому графу поиска в глубину из
вершины v0 = 1. «Прямые» ребра проведены сплошными линиями, а «обратные» пунктирными. Каждой вершине приписан ее ПГ-номер.
Из способа построения множеств Т и В непосредственно вытекают следующие утверждения.
Утверждение 73.1. Дуги множества Т образуют ориентированное остовное дерево с корнем в вершине v0. Это остовное дерево часто называют остовным глубинным деревом (ОГД). Обозначать
его будем также через Т.
Утверждение 73.2. Если ориентированное ребро (х, у) принадлежит В, то ПГ(х)>ПГ(у), т. е. «обратные» ребра всегда ведут к ранее пройденным вершинам.
Поиск в глубину используется в качестве составной тасти во многих алгоритмах. Отметим одну задачу, решение которой можно получить с помощью алгоритма A1 фазу, почти без дополнительных вычислительных затрат. Это — задача выделения связных компонент графа. Чтобы решить ее за время O( | EG|+ | G|), достаточно один раз просмотреть список вершин графа, выполняя следующие действия. Если просматриваемая вершина vl имеет ПГ-номер, то перейти к следующей. Иначе — положить v0 = vl ПГ(v0) = k + 1, где k — последний присвоенный ПГ-номер, и применить поиск в глубину.После его окончания (т. е. выделения компоненты, содержащей vl) продолжить просмотр списка, перейти к вершине vl+1. Различать вершины разных компонент можно, например, по их ПГ-номерам, если для каждой компоненты запомнить последний ПГ-номер.
Дата публикования: 2015-01-23; Прочитано: 304 | Нарушение авторского права страницы | Мы поможем в написании вашей работы!