Использование обхода в глубину для поиска точек сочленения — различия между версиями
(→Реализация) |
|||
Строка 1: | Строка 1: | ||
− | Дан [[Отношение связности, компоненты связности|связный]] [[Основные определения теории графов|неориентированный граф]] <tex> G </tex>. Найти все [[Точка сочленения, эквивалентные определения|точки сочленения]] в <tex> G </tex> за время <tex> O(|V| + |E|)</tex> | + | {{Задача |
+ | |definition=Дан [[Отношение связности, компоненты связности|связный]] [[Основные определения теории графов|неориентированный граф]] <tex> G </tex>. Найти все [[Точка сочленения, эквивалентные определения|точки сочленения]] в <tex> G </tex> за время <tex> O(|V| + |E|)</tex> | ||
+ | }} | ||
== Алгоритм == | == Алгоритм == | ||
Строка 19: | Строка 21: | ||
− | [[Файл:Joint_point_2_rsz.png|280px|thumb|left|Красным цветом обозначены точки сочленения<br>Синим — ребра по которым идет DFS]] | + | [[Файл:Joint_point_2_rsz.png|280px|thumb|left| <font color=red>Красным</font> цветом обозначены точки сочленения<br><font color=blue>Синим</font> — ребра по которым идет DFS]] |
Пусть <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> в дереве поиска. | ||
− | Тогда из вершины <tex>u</tex> или её потомка есть обратное ребро в её предка <tex>\Leftrightarrow \exists</tex> такой сын <tex>v</tex>, что <tex>up[v] | + | Тогда из вершины <tex>u</tex> или её потомка есть обратное ребро в её предка <tex>\Leftrightarrow \exists</tex> такой сын <tex>v</tex>, что <tex>up[v] \geqslant tin[u]</tex>. |
− | Таким образом, если для текущей вершины <tex>v \ne root </tex> существует непосредственный сын <tex>v</tex>: <tex>up[v] \ | + | Таким образом, если для текущей вершины <tex>v \ne root </tex> существует непосредственный сын <tex>v</tex>: <tex>up[v] \geqslant tin[u]</tex>, то вершина <tex>u</tex> является точкой сочленения, в противном случае она точкой сочленения не является. |
<br clear="all"> | <br clear="all"> | ||
Строка 39: | Строка 41: | ||
'''for''' u: (v, u) '''in''' G | '''for''' u: (v, u) '''in''' G | ||
'''if''' u == p | '''if''' u == p | ||
− | continue | + | '''continue''' |
− | '''if''' visited[u] | + | '''if''' visited[u] |
up[v] = min(up[v], tin[u]) | up[v] = min(up[v], tin[u]) | ||
'''else''' | '''else''' | ||
dfs(u, v) | dfs(u, v) | ||
up[v] = min(up[v], tin[u]) | up[v] = min(up[v], tin[u]) | ||
− | '''if''' up[to] >= tin[v] && p != -1 <font color=darkgreen>//если граф состоит из 2 вершин и одного ребра, то p != -1 спасёт, иначе выведет 1 точку сочленения </font> | + | '''if''' up[to] >= tin[v] '''&&''' p != -1 <font color=darkgreen>// если граф состоит из 2 вершин и одного ребра, то p != -1 спасёт, иначе выведет 1 точку сочленения </font> |
v — cutpoint | v — cutpoint | ||
− | '''if''' v | + | '''if''' v '''is''' root |
v — cutpoint | v — cutpoint | ||
'''for''' i = 1 '''to''' n | '''for''' i = 1 '''to''' n | ||
− | '''if''' visited[i] | + | '''if''' '''not''' visited[i] |
dfs(i, -1) | dfs(i, -1) | ||
Версия 22:33, 8 января 2017
Задача: |
Дан связный неориентированный граф . Найти все точки сочленения в за время |
Содержание
Алгоритм
Теорема: |
Пусть обхода в глубину, — корень . Вершина — точка сочленения — сын : из или любого потомка вершины нет обратного ребра в предка вершины . — точка сочленения имеет хотя бы двух сыновей в дереве поиска в глубину. — дерево |
Доказательство: |
|
Пусть
— время входа поиска в глубину в вершину . Через обозначим минимум из времени захода в саму вершину , времен захода в каждую из вершин , являющуюся концом некоторого обратного ребра , а также из всех значений для каждой вершины , являющейся непосредственным сыном в дереве поиска.Тогда из вершины
или её потомка есть обратное ребро в её предка такой сын , что .Таким образом, если для текущей вершины
существует непосредственный сын : , то вершина является точкой сочленения, в противном случае она точкой сочленения не является.
Псевдокод
function findCutPoints(G[n]: Graph): // функция принимает граф G с количеством вершин n и выполняет поиск точек сочленения во всем графе visited = array[n, false] function dfs(v: int, p: int): time = time + 1 up[v] = tin[v] = time visited[v] = true for u: (v, u) in G if u == p continue if visited[u] up[v] = min(up[v], tin[u]) else dfs(u, v) up[v] = min(up[v], tin[u]) if up[to] >= tin[v] && p != -1 // если граф состоит из 2 вершин и одного ребра, то p != -1 спасёт, иначе выведет 1 точку сочленения v — cutpoint if v is root v — cutpoint for i = 1 to n if not visited[i] dfs(i, -1)
См. также
Источники информации
- Асанов М., Баранский В., Расин В. — Дискретная математика: Графы, матроиды, алгоритмы — Лань, 2010. — 368 с. — ISBN 978-5-8114-1068-2
- MAXimal :: algo :: Поиск точек сочленения