Использование обхода в глубину для поиска точек сочленения — различия между версиями
м |
м |
||
| Строка 6: | Строка 6: | ||
Пусть <tex>T</tex> — дерево [[Обход в глубину, цвета вершин|обхода в глубину]], <tex>root</tex> — корень <tex>T</tex>. Вершина <tex>u \ne root</tex> — точка сочленения <tex>\Leftrightarrow \exists v \in T</tex> — сын <tex>u</tex> : из <tex>v</tex> или любого потомка вершины <tex>v</tex> нет обратного ребра в предка вершины <tex>u</tex>. <tex>root</tex> — точка сочленения <tex>\Leftrightarrow root</tex> имеет хотя бы двух сыновей в дереве поиска в глубину. | Пусть <tex>T</tex> — дерево [[Обход в глубину, цвета вершин|обхода в глубину]], <tex>root</tex> — корень <tex>T</tex>. Вершина <tex>u \ne root</tex> — точка сочленения <tex>\Leftrightarrow \exists v \in T</tex> — сын <tex>u</tex> : из <tex>v</tex> или любого потомка вершины <tex>v</tex> нет обратного ребра в предка вершины <tex>u</tex>. <tex>root</tex> — точка сочленения <tex>\Leftrightarrow root</tex> имеет хотя бы двух сыновей в дереве поиска в глубину. | ||
|proof= | |proof= | ||
| − | [[Файл:Joint_point_1.png| | + | [[Файл:Joint_point_1.png|50px |thumb| | Рисунок к <tex>\Leftarrow</tex>]] |
<tex>\Leftarrow</tex> | <tex>\Leftarrow</tex> | ||
| Строка 18: | Строка 18: | ||
| − | [[Файл:Joint_point_2.png| | + | [[Файл:Joint_point_2.png| 400px|thumb|Красным цветом обозначены точки сочленения]] |
Пусть <tex>tin[u]</tex> — время входа поиска в глубину в вершину <tex>u</tex>. Через <tex>up[u]</tex> обозначим минимум из времени захода в саму вершину <tex>tin[u]</tex>, времен захода в каждую из вершин <tex>p</tex>, являющуюся концом некоторого обратного ребра <tex>(u,p)</tex>, а также из всех значений <tex>up[v]</tex> для каждой вершины <tex>v</tex>, являющейся непосредственным сыном <tex>u</tex> в дереве поиска. | Пусть <tex>tin[u]</tex> — время входа поиска в глубину в вершину <tex>u</tex>. Через <tex>up[u]</tex> обозначим минимум из времени захода в саму вершину <tex>tin[u]</tex>, времен захода в каждую из вершин <tex>p</tex>, являющуюся концом некоторого обратного ребра <tex>(u,p)</tex>, а также из всех значений <tex>up[v]</tex> для каждой вершины <tex>v</tex>, являющейся непосредственным сыном <tex>u</tex> в дереве поиска. | ||
Версия 23:15, 4 июня 2012
Алгоритм
Дан связный неориентированный граф. Требуется найти все точки сочленения в нем.
| Теорема: |
Пусть — дерево обхода в глубину, — корень . Вершина — точка сочленения — сын : из или любого потомка вершины нет обратного ребра в предка вершины . — точка сочленения имеет хотя бы двух сыновей в дереве поиска в глубину. |
| Доказательство: |
|
|
Пусть — время входа поиска в глубину в вершину . Через обозначим минимум из времени захода в саму вершину , времен захода в каждую из вершин , являющуюся концом некоторого обратного ребра , а также из всех значений для каждой вершины , являющейся непосредственным сыном в дереве поиска.
Тогда из вершины или её потомка есть обратное ребро в её предка такой сын , что .
Таким образом, если для текущей вершины существует непосредственный сын : , то вершина является точкой сочленения, в противном случае она точкой сочленения не является.
Реализация
dfs(, ) Помечаем вершину , как посещенную ++ 0 for ( : из ) if ( родитель ) Переходим к следующей итерации цикла if ( посещено) // — предок вершины , — обратное ребро else // — ребенок вершины ++ dfs() if ( >= ) if ( корень) main() ... for ( из ) if ( не посещен) dfs(, -1);
Время работы алгоритма совпадает с временем работы .
Источники
Асанов М., Баранский В., Расин В. - Дискретная математика: Графы, матроиды, алгоритмы — Ижевск: ННЦ "Регулярная и хаотическая динамика", 2001, 288 стр.