Использование обхода в глубину для поиска точек сочленения — различия между версиями
(Новая страница: «== Задача == Дан связный [[Основные определения…») |
|||
Строка 14: | Строка 14: | ||
== Реализация == | == Реализация == | ||
− | + | В массиве <tex>answer[]</tex> для каждой вершины содержится булево значение - является она точкой сочленения или нет. Изначально все значения '''false'''. | |
− | + | ||
− | + | '''dfs'''<tex>(u, \, prev)</tex> | |
− | + | <tex>used[u] \leftarrow</tex>'''true''' | |
− | + | <tex>tin[u] \leftarrow time</tex> //задание времени входа в вершину u | |
− | + | <tex>up[u] \leftarrow time</tex> //задание начального значения up для вершины u | |
− | + | <tex>time \leftarrow time + 1</tex> | |
− | + | <tex>count \leftarrow 0</tex> //счетчик количества детей вершины u в дереве обхода | |
− | used[u] | + | '''for '''<tex>(v : uv \in E)</tex> |
− | tin[u] | + | '''if '''<tex>v = prev</tex> |
− | + | '''continue''' | |
− | for (v : uv | + | '''if '''<tex>used[v]</tex> //v - предок вершины u, uv - обратное ребро |
− | + | <tex>up[u] \leftarrow min(up[u], \, tin[v])</tex> | |
− | if | + | '''else''' //v - ребенок вершины u |
− | continue | + | <tex>count \leftarrow count + 1</tex> |
− | if | + | '''dfs'''<tex>(v, u)</tex> |
− | up[u] | + | <tex>up[u] \leftarrow min(up[u], \, up[v])</tex> |
− | else | + | '''if '''<tex>up[v] \ge tin[u]</tex> |
− | + | <tex>answer[u] \leftarrow</tex>'''true''' //не существует обратного ребра из вершины v или ее потомка в предка вершины u. вершина u - точка сочленения | |
− | + | + | '''if '''<tex>p = -1</tex> //является ли u корнем дерева обхода |
− | dfs(v, u) | + | <tex>answer[u] \leftarrow (count > 1)</tex>; //проверка количества детей у корня дерева |
− | up[u] | + | |
− | if | ||
− | answer[u] | ||
− | |||
− | |||
− | if | ||
− | answer[u] | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
== Источники == | == Источники == | ||
[http://e-maxx.ru/algo/ MAXimal::algo] | [http://e-maxx.ru/algo/ MAXimal::algo] |
Версия 06:42, 1 декабря 2010
Содержание
Задача
Дан связный неориентированный граф. Требуется найти все точки сочленения в нем.
Алгоритм
Запустим обход в глубину из произвольной вершины графа . Рассмотрим :
- . Тогда, если найдётся такой потомок вершины в дереве поиска, что ни из него, ни из какого-либо его потомка нет ребра в предка вершины , то вершина будет являться точкой сочленения. В противном случае, вершина не является точкой сочленения.
- . - точка сочленения имеет хотя бы двух сыновей в дереве поиска в глубину.
Пусть
- время входа поиска в глубину в вершину . Через обозначим минимум из времени захода в саму вершину , времен захода в каждую из вершин , являющуюся концом некоторого обратного ребра , а также из всех значений для каждой вершины , являющейся непосредственным сыном в дереве поиска.Тогда, из вершины
или её потомка есть обратное ребро в её предка такой сын , что .Таким образом, если для текущей вершины
непосредственный сын : , то вершина является точкой сочленения; в противном случае она точкой сочленения не является.Реализация
В массиве
для каждой вершины содержится булево значение - является она точкой сочленения или нет. Изначально все значения false.dfstrue //задание времени входа в вершину u //задание начального значения up для вершины u //счетчик количества детей вершины u в дереве обхода for if continue if //v - предок вершины u, uv - обратное ребро else //v - ребенок вершины u dfs if true //не существует обратного ребра из вершины v или ее потомка в предка вершины u. вершина u - точка сочленения if //является ли u корнем дерева обхода ; //проверка количества детей у корня дерева