Использование обхода в глубину для поиска точек сочленения
Задача
Дан связный неориентированный граф. Требуется найти все точки сочленения в нем.
Алгоритм
Запустим обход в глубину из произвольной вершины графа . Рассмотрим :
- . Тогда, если найдётся такой потомок вершины в дереве поиска, что ни из него, ни из какого-либо его потомка нет ребра в предка вершины , то вершина будет являться точкой сочленения. В противном случае, вершина не является точкой сочленения.
- . - точка сочленения имеет хотя бы двух сыновей в дереве поиска в глубину.
Пусть - время входа поиска в глубину в вершину . Через обозначим минимум из времени захода в саму вершину , времен захода в каждую из вершин , являющуюся концом некоторого обратного ребра , а также из всех значений для каждой вершины , являющейся непосредственным сыном в дереве поиска.
Тогда, из вершины или её потомка есть обратное ребро в её предка такой сын , что .
Таким образом, если для текущей вершины непосредственный сын : , то вершина является точкой сочленения; в противном случае она точкой сочленения не является.
Реализация
В массиве для каждой вершины содержится булево значение - является она точкой сочленения или нет. Изначально все значения false.
dfs true //задание времени входа в вершину u //задание начального значения up для вершины u //счетчик количества детей вершины u в дереве обхода for if continue if //v - предок вершины u, uv - обратное ребро else //v - ребенок вершины u dfs if true //не существует обратного ребра из вершины v или ее потомка в предка вершины u. вершина u - точка сочленения if //является ли u корнем дерева обхода ; //проверка количества детей у корня дерева