Использование обхода в глубину для поиска цикла — различия между версиями
(→С++) |
|||
Строка 18: | Строка 18: | ||
vector < vector<int> > graph; | vector < vector<int> > graph; | ||
vector<int> color; | vector<int> color; | ||
− | void dfs(int | + | |
+ | void dfs(int index) | ||
{ | { | ||
− | color[ | + | color[index] = 1; // красит вершину в серый цвет |
− | for (vector<int>::iterator i = graph[ | + | for (vector<int>::iterator i = graph[index].begin(); i != graph[index].end(); ++i) |
{ | { | ||
if ( color[*i] == 0 ) | if ( color[*i] == 0 ) | ||
dfs(*i); | dfs(*i); | ||
if ( color[*i] == 1 ) | if ( color[*i] == 1 ) | ||
− | print; | + | print(); // вывод ответа |
} | } | ||
− | color[ | + | color[index] = 2; // красит вершину в черный цвет |
} | } |
Версия 02:56, 10 ноября 2010
Содержание
Постановка задачи
Пусть дан ориентированный граф без петель и кратных рёбер. Требуется проверить наличие цикла в этом графе.
Решим эту задачу с помощью поиска в глубину за O (M).
Алгоритм
Произведём серию поисков в глубину в графе. Т.е. из каждой вершины, в которую мы ещё ни разу не приходили, запустим поиск в глубину, который при входе в вершину будет красить её в серый цвет, а при выходе - в чёрный. И если поиск в глубину пытается пойти в серую вершину, то это означает, что мы нашли цикл.
Сам цикл можно восстановить проходом по массиву предков.
Реализация
Здесь приведена реализация алгоритма на С++.
С++
vector < vector<int> > graph; vector<int> color; void dfs(int index) { color[index] = 1; // красит вершину в серый цвет for (vector<int>::iterator i = graph[index].begin(); i != graph[index].end(); ++i) { if ( color[*i] == 0 ) dfs(*i); if ( color[*i] == 1 ) print(); // вывод ответа } color[index] = 2; // красит вершину в черный цвет }