Построение компонент вершинной двусвязности — различия между версиями
Novik (обсуждение | вклад) (→Однопроходный алгоритм) |
Novik (обсуждение | вклад) |
||
| Строка 75: | Строка 75: | ||
<br> | <br> | ||
Во время алгоритма совершается один проход <tex>dfs</tex>, который работает за <tex>O(|V| + |E|)</tex>. Внутри него совершается еще цикл, который суммарно выполняет <tex>O(|E|)</tex> операций, т.к. каждое ребро может быть добавлено в стек только один раз. Следовательно, общее время работы алгоритма <tex>O(|V| + |E|) + O(|E|) = O(|V| + |E|)</tex> | Во время алгоритма совершается один проход <tex>dfs</tex>, который работает за <tex>O(|V| + |E|)</tex>. Внутри него совершается еще цикл, который суммарно выполняет <tex>O(|E|)</tex> операций, т.к. каждое ребро может быть добавлено в стек только один раз. Следовательно, общее время работы алгоритма <tex>O(|V| + |E|) + O(|E|) = O(|V| + |E|)</tex> | ||
| + | |||
| + | == См. также == | ||
| + | * [[Использование обхода в глубину для поиска точек сочленения]] | ||
| + | * [[Стек]] | ||
| + | * [[Построение компонент реберной двусвязности]] | ||
== Источники информации == | == Источники информации == | ||
Версия 22:34, 10 ноября 2015
Содержание
Двупроходный алгоритм
Найти компоненты вершинной двусвязности неориентированного графа можно с помощью обхода в глубину.
Первый проход:
Используем первый проход, чтобы найти точки сочленения.
Второй проход:
Точка сочленения принадлежит как минимум двум компонентам вершинной двусвязности.
Вершина является точкой сочленения, если у нее есть сын .
Это также значит, что ребро содержится в другой компоненте вершинной двусвязности, нежели ребро по которому мы пришли в вершину , используя поиск в глубину. Получается, что перейдя по этому ребру, мы окажемся в другой компоненте вершинной двусвязности.
Используем это свойство, чтобы окрасить компоненты вершинной двусвязности в различные цвета.
Псевдокод второго прохода
function (, color, parent): for : if == parent continue if not visited[] if up[] tin[] newColor = maxColor++ col[] = newColor dfs(, newColor, ) else col[] = color dfs(, color, ) else if up[] tin[] col[] = color for : if not visited[] dfs(, -1, -1) |
Ребра каждой из компонент вершинной двусвязности окажутся окрашенными в свой цвет.
В алгоритме выполняется два прохода , каждый из которых работает . Значит время работы алгоритма .
Однопроходный алгоритм
Заведем стек, в который будем записывать все дуги в порядке их обработки. Если обнаружена точка сочленения, дуги очередного блока окажутся в этом стеке, начиная с дуги дерева обхода, которая привела в этот блок, до верхушки стека.
Таким образом, каждый раз находя компоненту вершинной двусвязности мы сможем покрасить все ребра, содержащиеся в ней, в новый цвет.
Доказательство корректности алгоритма
Предположим, что граф содержит точку сочленения , за которой следует один или несколько блоков. Вершины из этих блоков образуют подмножество . В таком случае:
- Все вершины являются потомками в дереве обхода;
- Все вершины будут пройдены в течение периода серого состояния ;
- В не может быть обратных дуг из в .
Значит все дуги будут будут добавлены в стек после дуги ведущей из точки сочленения в блок. В стеке в момент обнаружения точки сочленения будут находиться только дуги блока, связанного с ней, т.к. блоки найденные до него (если таковые имеются) будет уже извлечены из стека и покрашены в свой цвет.
Псевдокод
function (, parent): tin[] = up[] = time++ for : if == parent continue if not visited[] stack.push() dfs() if up[] tin[] color = maxColor++ while stack.top() != () colors[stack.top()] = color stack.pop() colors[] = color stack.pop() if up[] < up[] up[] = up[] else if tin[] < tin[] stack.push() else if up[] > tin[] up[] = up[]
for : if not visited[] time = 0 dfs(, -1)
Во время алгоритма совершается один проход , который работает за . Внутри него совершается еще цикл, который суммарно выполняет операций, т.к. каждое ребро может быть добавлено в стек только один раз. Следовательно, общее время работы алгоритма
См. также
- Использование обхода в глубину для поиска точек сочленения
- Стек
- Построение компонент реберной двусвязности
Источники информации
- В.А.Кузнецов, А.М.Караваев. "Оптимизация на графах" - Петрозаводск, Издательство ПетрГУ 2007