Использование обхода в глубину для поиска цикла — различия между версиями
(→Доказательство) |
(→Доказательство) |
||
| Строка 12: | Строка 12: | ||
= Доказательство = | = Доказательство = | ||
| − | Пусть дан граф <tex>G</tex>. Запустим <tex>dfs(G)</tex>. Рассмотрим выполнение процедуры поиска в глубину от некоторой вершины <tex> v </tex>. Так как все серые вершины лежат в стеке рекурсии, то для них вершина <tex> v </tex> достижима по белым путям. Тогда если из рассматриваемой вершины <tex> v </tex> существует ребро в серую вершину <tex> u </tex>, то это значит что из вершины. | + | Пусть дан граф <tex>G</tex>. Запустим <tex>dfs(G)</tex>. Рассмотрим выполнение процедуры поиска в глубину от некоторой вершины <tex> v </tex>. Так как все серые вершины лежат в стеке рекурсии, то для них вершина <tex> v </tex> достижима по белым путям. Тогда если из рассматриваемой вершины <tex> v </tex> существует ребро в серую вершину <tex> u </tex>, то это значит, что из вершины <tex> u </tex> существует путь в <tex> v </tex> и из вершины <tex> v </tex> существует путь в <tex> u </tex>. И так как оба эти пути реберно не пересекающиеся, то существует цикл. |
= Реализация = | = Реализация = | ||
Версия 07:12, 7 декабря 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; // красит вершину в черный цвет
}