Построение компонент рёберной двусвязности — различия между версиями

Материал из Викиконспекты
Перейти к: навигация, поиск
(Двупроходный алгоритм)
Строка 44: Строка 44:
 
Можно найти компоненты реберной двусвязности за один проход, используя стек.
 
Можно найти компоненты реберной двусвязности за один проход, используя стек.
 
   
 
   
Алгоритм, если мы посетили вершину, то добавляем её в стек. Так же как раньше <tex>ret[v]</tex> и <tex>enter[v]</tex>. Теперь определим, когда надо окрасить компоненту.
+
Рекурсивый алгоритм на основе обхода в глубину.
Если мы возвращаясь обратно оказались в вершине, которая является вершиной моста, то все вершины, находящиеся, до текущей в стеке, принадлежат этой компоненте. Это следует из того, что [[Граф компонент реберной двусвязности | граф блоков и мостов, является деревом]]. По свойству обхода в ширину, мы окажемся в висячей вершине, покрасим её, то есть эту компоненту покрасим. Её можно выкинут и рассматривать оставшийся граф. Действуя по аналогии мы всегда выкидываем компоненту реберной двусвязности следовательно, если мы вернулись в вершину, которая была концом нашего моста, то все вершины лежащие до нашей в стеке, принадлежат данной компоненте.  
+
Если мы посетили вершину, то добавляем её в стек. Теперь определим, когда надо окрасить компоненту.
 +
Если мы возвращаясь (в рекурсии) обратно оказались в вершине, которая является вершиной моста, то все вершины, находящиеся, до текущей в стеке, принадлежат этой компоненте. Это следует из того, что [[Граф компонент реберной двусвязности | граф блоков и мостов, является деревом]]. По свойству обхода в глубину, мы окажемся в висячей вершине, покрасим её, то есть эту компоненту покрасим. Её можно выкинут и рассматривать оставшийся граф. Действуя по аналогии мы всегда выкидываем компоненту реберной двусвязности следовательно, если мы вернулись в вершину, которая была концом нашего моста, то все вершины лежащие до нашей в стеке, принадлежат данной компоненте, либо если моста нет, то окрашиваемся всё, что лежит в стеке.  
 
Псевдокод:
 
Псевдокод:
  
 
   '''void paint(int v):
 
   '''void paint(int v):
     maxcolor++;
+
     maxcolor++
 
       while (пока вершина стека не вершина <tex>v</tex> и стек не пустой)
 
       while (пока вершина стека не вершина <tex>v</tex> и стек не пустой)
         извлекаем вершину стека и красим её;
+
         извлекаем вершину стека и красим её  
 
 
 
    
 
    
Строка 57: Строка 58:
 
   '''void dfs(вершина v, предок вершины p):
 
   '''void dfs(вершина v, предок вершины p):
 
     добавляем вершину в в стек;
 
     добавляем вершину в в стек;
     state[v] = 1;
+
     state[v] = 1
     ret[v] = enter[v] = ++time;
+
     ret[v] = enter[v] = ++time
 
     для всех  вершин u смежных v:
 
     для всех  вершин u смежных v:
 
       если (u == parent):  
 
       если (u == parent):  
 
         переходим к следующей итерации
 
         переходим к следующей итерации
 
       если (state[u] = 1):
 
       если (state[u] = 1):
           ret[v] = min(ret[v], enter[u]);
+
           ret[v] = min(ret[v], enter[u])
 
         иначе:
 
         иначе:
 
           если (state[u] = 0):
 
           если (state[u] = 0):
             dfs(u, v);
+
             dfs(u, v)
             ret[v] = min(ret[v], ret[u]);
+
             ret[v] = min(ret[v], ret[u])
 
             если (enter[v] < ret[u]):  
 
             если (enter[v] < ret[u]):  
             paint(u);
+
             paint(u)
     state[v] = 2;
+
     state[v] = 2
 
   
 
   
  
Строка 78: Строка 79:
 
Итоговое время работы алгоритма <tex> O(|V| + |E|)</tex>.
 
Итоговое время работы алгоритма <tex> O(|V| + |E|)</tex>.
  
== См. также ==
+
== Визуализатор ==
* [[Обход в глубину, цвета вершин|Oбхода в глубину]]
 
* [[Использование обхода в глубину для поиска точек сочленения]]
 
* [[Построение компонент вершинной двусвязности]]
 
* [[Использование обхода в глубину для поиска мостов]]
 
 
* [http://rain.ifmo.ru/cat/view.php/vis/graph-general/bridges-2001| Визуализация построение компонент реберной двусзяности]
 
* [http://rain.ifmo.ru/cat/view.php/vis/graph-general/bridges-2001| Визуализация построение компонент реберной двусзяности]
  

Версия 08:33, 22 ноября 2011

Основные понятия

Построение компонент реберной двусвязности будет осуществляться с помощью обхода в глубину.

Двупроходный алгоритм

Первый способ найти искомые компоненты - сначала определить критерий перехода в новую компоненту реберной двусвязности, а затем покрасить вершины графа в нужные цвета.

Первый проход определяет для каждой вершины [math]v[/math] две величины: [math]enter(v)[/math] - время входа поиска в глубину в вершину и ret(v)

Определим критерий перехода к новой компоненте. Воспользуемся ранее доказанной леммой.

Основываясь на этом, определим алгоритм окраски вершин графа. Перешли по мосту, следовательно началась новая компонента.

Псевдокод второго прохода:

 void paint(v, цвет):
   colors(v) := цвет
   для всех вершин u, смежных v:
     если colors(u) равен нулю (вершина не покрашена):
       если ret(u) = enter(u):
         увеличиваем максимальный цвет
         paint(u, максимальный цвет)
       иначе:
         paint(u, цвет)
 ...
 обнуляем массив colors
 максимальный цвет := 0
 для всех вершин v графа:
   если colors(v) = 0:
     увеличиваем максимальный цвет
     paint(v, максимальный цвет)

Вершины каждой из компонент реберной двусвязности окажутся окрашенными в свой цвет.

Время работы алгоритма будет время работы двух запусков dfs, то есть 2 * [math] O(|V| + |E|)[/math], что есть [math] O(|V| + |E|)[/math].

Однопроходный алгоритм

Можно найти компоненты реберной двусвязности за один проход, используя стек.

Рекурсивый алгоритм на основе обхода в глубину. Если мы посетили вершину, то добавляем её в стек. Теперь определим, когда надо окрасить компоненту. Если мы возвращаясь (в рекурсии) обратно оказались в вершине, которая является вершиной моста, то все вершины, находящиеся, до текущей в стеке, принадлежат этой компоненте. Это следует из того, что граф блоков и мостов, является деревом. По свойству обхода в глубину, мы окажемся в висячей вершине, покрасим её, то есть эту компоненту покрасим. Её можно выкинут и рассматривать оставшийся граф. Действуя по аналогии мы всегда выкидываем компоненту реберной двусвязности следовательно, если мы вернулись в вершину, которая была концом нашего моста, то все вершины лежащие до нашей в стеке, принадлежат данной компоненте, либо если моста нет, то окрашиваемся всё, что лежит в стеке. Псевдокод:

 void paint(int v):
   maxcolor++
     while (пока вершина стека не вершина [math]v[/math] и стек не пустой)
       извлекаем вершину стека и красим её 


 void dfs(вершина v, предок вершины p):
   добавляем вершину в в стек;
   state[v] = 1
   ret[v] = enter[v] = ++time
   для всех  вершин u смежных v:
     если (u == parent): 
       переходим к следующей итерации
      	если (state[u] = 1):
         ret[v] = min(ret[v], enter[u])
       иначе:
         если (state[u] = 0):
           dfs(u, v)
           ret[v] = min(ret[v], ret[u])
           если (enter[v] < ret[u]): 
           paint(u)	
   state[v] = 2

Теперь две вершины имеют одинаковый цвет тогда и только тогда, когда они принадлежат одной компоненте реберной двусвязности.

Время работы dfs [math] O(|V| + |E|)[/math]. Покраска за [math] O(|V|) [/math]. Итоговое время работы алгоритма [math] O(|V| + |E|)[/math].

Визуализатор

Литература

Седжвик Роберт. Фундаментальные алгоритмы на C++. Часть 5: Алгоритмы на графах: Пер. с англ./Роберт Седжвик. — СПб.: ООО «ДиаСофтЮП», 2002. — С. 123-128

В.А.Кузнецов, А.М.Караваев. "Оптимизация на графах" - Петрозаводск, Издательство ПетрГУ 2007