Использование обхода в глубину для поиска компонент сильной связности — различия между версиями
(→Алгоритм) |
|||
Строка 1: | Строка 1: | ||
==Алгоритм== | ==Алгоритм== | ||
[[Файл:Dfs_strong.png|290px|thumb|Вершины 2, 4, 5 сильносвязаны.<br>Синим цветом обозначен обод DFS по инвертированным ребрам]] | [[Файл:Dfs_strong.png|290px|thumb|Вершины 2, 4, 5 сильносвязаны.<br>Синим цветом обозначен обод DFS по инвертированным ребрам]] | ||
− | [[Отношение_связности,_компоненты_связности#Сильная связность|Компоненты сильной | + | [[Отношение_связности,_компоненты_связности#Сильная связность|Компоненты сильной связности]] в графе <tex>G</tex> можно найти с помощью [[Обход_в_глубину,_цвета_вершин | поиска в глубину]] в 3 этапа: |
#Построить граф <tex>H</tex> с обратными (инвертированными) рёбрами | #Построить граф <tex>H</tex> с обратными (инвертированными) рёбрами | ||
#Выполнить в <tex>H</tex> поиск в глубину и найти <tex>f[u]</tex> — время окончания обработки вершины <tex>u</tex> | #Выполнить в <tex>H</tex> поиск в глубину и найти <tex>f[u]</tex> — время окончания обработки вершины <tex>u</tex> |
Версия 10:51, 16 ноября 2013
Содержание
Алгоритм
Компоненты сильной связности в графе можно найти с помощью поиска в глубину в 3 этапа:
- Построить граф с обратными (инвертированными) рёбрами
- Выполнить в поиск в глубину и найти — время окончания обработки вершины
- Выполнить поиск в глубину в , перебирая вершины во внешнем цикле в порядке убывания
Полученные на 3-ем этапе деревья поиска в глубину будут являться компонентами сильной связности графа
Так как компоненты сильной связности и графа совпадают, то первый поиск в глубину для нахождения можно выполнить на графе , а второй — на .
Доказательство корректности алгоритма
Теорема: |
Вершины и взаимно достижимы после выполнения алгоритма они принадлежат одному дереву обхода в глубину. |
Доказательство: |
Если вершины и были взаимно достижимы в графе , то на третьем этапе будет найден путь из одной вершины в другую, это означает, что по окончанию алгоритма обе вершины лежат в одном поддереве.
1) Вершины и лежат в одном и том же дереве поиска в глубину на третьем этапе алгоритма. Значит, что они обе достижимы из корня этого дерева.2) Вершина была рассмотрена вторым обходом в глубину раньше, чем и , значит время выхода из нее при первом обходе в глубину больше, чем время выхода из вершин и . Из этого мы получаем 2 случая:а) Обе эти вершины были достижимы из в инвертированном графе. А это означает взаимную достижимость вершин и и взаимную достижимость вершин и . А складывая пути мы получаем взаимную достижимость вершин и .б) Хотя бы одна не достижима из Значит, из случая а) и не существования случая б) получаем, что вершины в инвертированном графе, например . Значит и была не достижима из в инвертированном графе, так как время выхода - больше . Значит между этими вершинами нет пути, но последнего быть не может, потому что была достижима из по пункту 1). и взаимно достижимы в обоих графах. |
Время работы алгоритма
- Для того, чтобы инвертировать все ребра в графе, представленном в виде списка потребуется действий. Для матричного представления графа не нужно выполнять никакие действия для его инвертирования.
- Количество ребер в инвертированном равно количеству ребер в изначальном графе, поэтому поиск в глубину будет работать за
- Поиск в глубину в исходном графе выполняется за .
В итоге получаем, что время работы алгоритма
.Псевдокод
Пусть
— исходный граф, —инвертированный граф. В массиве будем хранить номера вершин в порядке окончания обработки поиском в глубину в графе . В результате получаем массив , который каждой вершине сопоставляет номер её компоненты.dfs1() for (всех смежных с ) if (вершина не посещена) dfs1( ) Добавляем вершину в конец списка dfs2( ) for (всех смежных с ) if (если вершина еще не находится ни в какой компоненте) dfs2( ) main() считываем исходные данные, формируем массивы и for (по всем вершинам графа ) if (вершина не посещена) dfs1(i) for (по всем вершинам списка в обратном порядке) if (если вершина не находится ни в какой компоненте) dfs2( ) ++
Литература
- Р.Седжвик. "Фундаментальные алгоритмы на С++. Алгоритмы на графах" - СПб, ДиаСофтЮП, 2002