Скажите, пожалуйста, можно ли еще получить документ о прохождении курса ("Графы и алгоритмы", декабрь 2020) после предоставления всех дополнительных необходимых документов? |
Блоки
Выявление блоков
Рассмотрим связный граф и в нем DFS-дерево
,
построенное поиском в глубину из стартовой вершины
.
Через
будем обозначать отца вершины
в этом дереве, при этом считаем, что
.
Будем также считать, что в процессе обхода графа вычисляются
значения функций
и
, определенных
в предыдущем разделе.
Пусть - блок графа, а
- вершина
этого блока
с наименьшим значением
. Иначе говоря,
- вершина
блока, посещаемая при обходе первой. Среди сыновей вершины
имеется единственная вершина
, принадлежащая
блоку
.
Вершину
будем называть начальной вершиной, а
ребро
-
начальным ребром блока
.
Теорема 4. Пусть в DFS-дереве
.
Ребро
является начальным ребром
некоторого блока тогда и только тогда, когда
.
Доказательство. Если , то для каждого сына
вершины
имеет место равенство
и ребро
является начальным ребром некоторого блока.
Пусть и
- начальное ребро
блока
.
Предположим, что
. Это означает, что имеется
ребро,
соединяющее некоторого потомка вершины
с собственным предком
вершины
. Но тогда ребра
и
оказываются
циклически связанными, а отсюда следует, что вершина
принадлежит блоку
. Но это противоречит тому,
что
-
начальная вершина блока, так как
.
Обратно, пусть . Тогда
вершина
является
шарниром графа. Рассмотрим поддерево, состоящее из всех потомков
вершины
. Ни одна из вершин этого поддерева не смежна ни с
одной отличной
от
вершиной вне поддерева. Значит, все вершины блока,
содержащего ребро
, принадлежат этому поддереву,
и
-
начальное ребро этого блока.
В основе описываемого ниже алгоритма выявления блоков лежит рекурсивная
процедура вычисления функции из предыдущего раздела.
Напомним,
что
есть наименьший из глубинных номеров вершин, смежных
с потомками вершины
. Переменная
- счетчик
блоков,
-
множество вершин блока с номером
. В стеке
накапливаются вершины графа, впервые встречающиеся в процессе
обхода (т.е. превращающиеся из новых в открытые).
Множества вершин блоков строит процедура NewBlock. Она вызывается всякий
раз, когда обнаруживается начальное ребро некоторого
блока
(выполняется равенство
). Эта процедура
включает в
новое множество
вершины
,
и
все
вершины, находящиеся в стеке выше вершины
. Эти вершины удаляются
из стека (кроме вершины
, которая является начальной вершиной
блока и может принадлежать еще и другим блокам). Для обоснования
алгоритма остается убедиться в том, что блок состоит именно из этих
вершин. Доказательство можно провести индукцией по номеру блока
.
Вершина
помещается в стек
, когда она становится
открытой, а условие
проверяется для вершины
тогда, когда она превращается в закрытую. Все вершины, помещаемые в стек
между этими двумя событиями, будут потомками вершины
в DFS-дереве, каждый потомок вершины
будет помещен в стек
после
, и когда
становится закрытой, все эти
вершины уже
закрыты. Если
, то среди потомков вершины
нет
начальных вершин блоков (иначе номер этого блока был бы больше 1),
следовательно, блок c начальным ребром
состоит из всех
этих
вершин и вершины
. Если же
, то, по
предположению индукции, все
вершины других блоков, состоящих из потомков вершины
, не
принадлежащие блоку
, к моменту обнаружения начального ребра
уже удалены из стека, следовательно,
состоит в точности из
,
и вершин, находящихся в
стеке
выше вершины
.
Алгоритм 1. Выявление блоков
-
for
do
-
for
do if
then Blocks
Procedure
-
for
do
-
if
-
then Blocks(
)
-
if
then NewBlock
-
else
Procedure NewBlock
- repeat
-
until