Скажите, пожалуйста, можно ли еще получить документ о прохождении курса ("Графы и алгоритмы", декабрь 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