Использование обхода в глубину для поиска компонент сильной связности
Постановка задачи
Дан ориентированный граф . Требуется найти в этом графе компоненты сильной связанности.
Алгоритм
Данная задачи решается с помощью поиска в глубину в 3 этапа:
- Построить граф с обратными (инвертированными) рёбрами
- Выполнить в поиск в глубину и найти - время окончания обработки вершины
- Выполнить поиск в глубину в , перебирая вершины во внешнем цикле в порядке убывания
Полученные на 3-ем этапе деревья поиска в глубину будут являться компонентами сильной связности графа
Так как компоненты сильной связности и графа совпадают, то первый поиск в глубину для нахождения можно выполнить на графе , а второй - на .
Доказательство
Докажем два утверждения:
- если вершины и взаимно достижимы, то они после работы алгоритма окажутся в одной компоненте сильной связности
- если вершины и после работы алгоритма оказались в одной компоненте сильной связности, то они взаимно достижимы
Пример реализации
vector<vector<int>> g, h; //g хранит граф в виде списка смежностей, h - инвертированный vector<int> color, ord, component; //цвет вершины, список вершин в порядке окончания обработки, номер компоненты, к который относиться вершина int col; //номер текущей компоненты void dfs(int & v) //первый поиск в глубину, определяющий порядок обхода { color[v] = 1; for (unsigned i = 0; i < g[v].size(); ++i) { if (color[g[v][i]] == 0) dfs(g[v][i]); } ord.push_back(v); //добавляем вершину v в конец списка ord[] } void dfs2(int & v) //второй поиск в глубину, выявляет компоненты сильной связности в графе { component[v] = col; //помечаем вершину v как принадлежащую компоненте с номером col for (unsigned i = 0; i < h[v].size(); ++i) { if (component[h[v][i]] == 0) dfs2(h[v][i]); } } int main() { ... //считываем исходные данные, формируем массивы g и h for (int i = 1; i <= n; ++i) //формируем массив ord[] { if (color[i] == 0) dfs(i); } col = 1; for (int i = ord.size(); i > 0; --i) //ищем компоненты связности, вызывая вершины в обратном порядке { //от сохранённого в ord[], что соответствует уменьшению времени конца обработки f[] if (component[ord[i - 1]] == 0) dfs2(ord[i - 1]), col++; } }
По окончании выполнения алгоритма в
имеем номер компоненты, к которой принадлежит вершина .Литература
- Р.Седжвик. "Фундаментальные алгоритмы на С++. Алгоритмы на графах" - СПб, ДиаСофтЮП, 2002