Использование обхода в глубину для поиска точек сочленения — различия между версиями
(→Алгоритм) |
(→Алгоритм) |
||
Строка 2: | Строка 2: | ||
== Алгоритм == | == Алгоритм == | ||
+ | |||
{{Теорема | {{Теорема | ||
|statement= | |statement= | ||
Строка 11: | Строка 12: | ||
#Удалим <tex>u</tex> из <tex>G</tex>. Докажем, что не существует пути из <tex>v</tex> в любого предка вершины <tex>u</tex>. Пусть это не так. Тогда <tex>\exists x \in T</tex> — предок <tex>u</tex> : <tex>\exists</tex> путь из <tex>v</tex> в <tex>x</tex> в <tex>G \backslash u</tex>. Пусть <tex>w</tex> — предпоследняя вершина на этом пути, <tex>w</tex> — потомок <tex>v</tex>. <tex>(w, x)</tex> — не ребро дерева <tex>T</tex>(в силу единственности пути в дереве) <tex>\Rightarrow (w, x)</tex> — обратное ребро, что противоречит условию. | #Удалим <tex>u</tex> из <tex>G</tex>. Докажем, что не существует пути из <tex>v</tex> в любого предка вершины <tex>u</tex>. Пусть это не так. Тогда <tex>\exists x \in T</tex> — предок <tex>u</tex> : <tex>\exists</tex> путь из <tex>v</tex> в <tex>x</tex> в <tex>G \backslash u</tex>. Пусть <tex>w</tex> — предпоследняя вершина на этом пути, <tex>w</tex> — потомок <tex>v</tex>. <tex>(w, x)</tex> — не ребро дерева <tex>T</tex>(в силу единственности пути в дереве) <tex>\Rightarrow (w, x)</tex> — обратное ребро, что противоречит условию. | ||
#Пусть у <tex>root</tex> хотя бы два сына. Тогда при удалении <tex>root</tex> не существует пути между его поддеревьями, так как не существует перекрестных ребер <tex>\Rightarrow root</tex> — точка сочленения. | #Пусть у <tex>root</tex> хотя бы два сына. Тогда при удалении <tex>root</tex> не существует пути между его поддеревьями, так как не существует перекрестных ребер <tex>\Rightarrow root</tex> — точка сочленения. | ||
− | + | ||
<tex>\Rightarrow</tex> | <tex>\Rightarrow</tex> | ||
#Докажем что из отрицания второго утверждения следует отрицание первого. Обозначим через <tex>G'</tex> граф, состоящий из вершин, не являющихся потомками <tex>u</tex>. Удалим вершину <tex>u</tex>. Очевидно, что граф <tex>G'</tex> и все поддеревья вершины <tex>u</tex> останутся связными, кроме того из каждого поддерева есть ребро в <tex>G' \Rightarrow G \backslash u</tex> — связный <tex>\Rightarrow u</tex> — не точка сочленения. | #Докажем что из отрицания второго утверждения следует отрицание первого. Обозначим через <tex>G'</tex> граф, состоящий из вершин, не являющихся потомками <tex>u</tex>. Удалим вершину <tex>u</tex>. Очевидно, что граф <tex>G'</tex> и все поддеревья вершины <tex>u</tex> останутся связными, кроме того из каждого поддерева есть ребро в <tex>G' \Rightarrow G \backslash u</tex> — связный <tex>\Rightarrow u</tex> — не точка сочленения. |
Версия 17:34, 8 января 2017
Дан связный неориентированный граф . Найти все точки сочленения в за время
Содержание
Алгоритм
Теорема: |
Пусть обхода в глубину, — корень . Вершина — точка сочленения — сын : из или любого потомка вершины нет обратного ребра в предка вершины . — точка сочленения имеет хотя бы двух сыновей в дереве поиска в глубину. — дерево |
Доказательство: |
|
Красным цветом обозначены точки сочлененияСиним — ребра по которым идет DFS
Пусть — время входа поиска в глубину в вершину . Через обозначим минимум из времени захода в саму вершину , времен захода в каждую из вершин , являющуюся концом некоторого обратного ребра , а также из всех значений для каждой вершины , являющейся непосредственным сыном в дереве поиска.
Тогда из вершины
или её потомка есть обратное ребро в её предка такой сын , что .Таким образом, если для текущей вершины
существует непосредственный сын : , то вершина является точкой сочленения, в противном случае она точкой сочленения не является.
Реализация
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] == true 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 — root v — cutpoint for i = 1 to n if visited[i] == false dfs(i, -1)
См. также
Источники информации
- Асанов М., Баранский В., Расин В. — Дискретная математика: Графы, матроиды, алгоритмы — Лань, 2010. — 368 с. — ISBN 978-5-8114-1068-2
- MAXimal :: algo :: Поиск точек сочленения