- •Элементарные алгоритмы для работы с графами
- •Работа алгоритма[править | править вики-текст]
- •Неформальное описание[править | править вики-текст]
- •Формальное описание[править | править вики-текст]
- •Алгоритм поиска в глубину[править | править вики-текст]
- •Нерекурсивные варианты[править | править вики-текст]
- •Общая идея
- •[Править]Пошаговое представление
- •[Править]Реализация
- •[Править]Время работы
- •[Править]Цвета вершин
- •Топологическая сортировка и сильно связные компоненты
- •↑ Пример ориентированного неотсортированного графа, к которому применима топологическая сортировка
- •Пример работы алгоритма[править | править вики-текст]
- •Алгоритмы[править | править вики-текст]
- •Минимальные остовные деревья (мst)
- •Введение
- •Постановка задачи
- •Кратчайшие пути
- •Давайте придумаем что-нибудь простое
- •А если я педант?
- •Задача о максимальном потоке
- •[Править]Определение потока
- •[Править]Пример
- •Увеличивающие пути. Теорема Бержа
- •Алгоритм Эдмондса. Сжатие цветков
- •Эффективная реализация
- •Оптимизация: предварительное построение паросочетания
- •Случай двудольного графа
- •Дальнейшая оптимизация
- •[Править]Реализация
- •[Править]Оценка производительности
- •[Править]Пример несходящегося алгоритма
- •[Править]Оценка быстродействия
- •[Править]Литература
- •Максимальные паросочетания[править | править вики-текст]
- •Описание алгоритма Необходимые определения
- •Теорема Бержа
- •Алгоритм Куна
- •Время работы
- •Реализация
- •Улучшенная реализация
- •[Править]Постановка задачи
- •[Править]Решение
- •[Править]Псевдокод
- •Префиксы и суффиксы строки
- •Прямые переходы
- •[Править]Суффиксные ссылки
- •Основные определения и описание структуры[править | править вики-текст]
- •Свойства суффиксных деревьев[править | править вики-текст]
- •Требования суффиксного дерева к памяти[править | править вики-текст]
- •[Править]Недостатки
- •Метод хеширования
- •[Править]Алгоритм
- •[Править]Псевдокод
- •[Править]Время работы
- •[Править]Надёжность
- •Автоматные модели в программировании
- •[Править]Переходы между состояниями [править]Прямые переходы
- •[Править]Суффиксные ссылки
- •[Править]Псевдокод
- •[Править]Пример использования
- •[Править]Псевдокод
- •[Править]Пример
- •[Править]Время работы
- •[Править]Эффективный алгоритм
- •[Править]Псевдокод
- •[Править]Время работы
- •[Править]Построение префикс-функции по z-функции [править]Постановка задачи
- •[Править]Описание алгоритма
- •Приближенные алгоритмы решения np-трудных задач
Алгоритм поиска в глубину[править | править вики-текст]
Пусть
задан граф
,
где
—
множество вершин графа,
—
множество ребер графа. Предположим, что
в начальный момент времени все вершины
графа окрашены в белый цвет.
Выполним следующие действия:
Пройдём по всем вершинам
.Если вершина белая, выполним для неё DFS(v).
Процедура
DFS (параметр — вершина
)
Перекрашиваем вершину в серый цвет.
Для всякой вершины
, смежной с
вершиной
и
окрашенной в белый цвет, рекурсивно выполняем
процедуру DFS(w)[2].Перекрашиваем вершину в чёрный цвет.
Часто используют двухцветные метки — без серого, на 1-м шаге красят сразу в чёрный цвет.
Нерекурсивные варианты[править | править вики-текст]
На больших графах поиск в глубину серьёзно нагружает стек вызовов. Если есть риск переполнения стека, используют нерекурсивные варианты поиска.
Первый вариант: можно сэмулировать стек вызова программно: для каждой из серых вершин в стеке будет храниться её номер и номер текущей смежной вершины .
Процедура DFS (параметр — вершина )
Кладём на стек пару
.
Перекрашиваем вершину
в серый цвет.Пока стек не пуст…
Берём верхнюю пару
,
не извлекая её из стека.Находим вершину
,
смежную с
и
следующую за
.Если таковой нет, извлекаем из стека, перекрашиваем вершину в чёрный цвет.
В противном случае присваиваем
,
прямо в стеке.Если к тому же вершина белая, кладём на стек пару
,
перекрашиваем
в серый цвет.
Второй вариант: можно в каждой из «серых» вершин держать текущее и указатель на предыдущую (ту, из которой пришли).
Третий вариант работает, если хватает двухцветных меток.
Процедура DFS (параметр — вершина )
Кладём на стек вершину .
Пока стек не пуст…
Берём верхнюю вершину .
Если она белая…
Перекрашиваем её в чёрный цвет.
Кладём в стек все смежные с белые вершины.
Общая идея
Общая идея алгоритма состоит в следующем: для каждой не пройденной вершины необходимо найти все не пройденные смежные вершины и повторить поиск для них.
[Править]Пошаговое представление
Выбираем любую вершину из еще не пройденных, обозначим ее как
.Запускаем процедуру
Помечаем вершину как пройденную
Для каждой не пройденной смежной с вершиной (назовем ее
)
запускаем
Повторяем шаги 1 и 2, пока все вершины не окажутся пройденными.
[Править]Реализация
vector<bool> visited; //вектор для хранения информации о пройденных и не пройденных вершинах
void dfs(int u)
{
visited[u] = true; //помечаем вершину как пройденную
for (v таких, что (u, v) — ребро в G) //проходим по смежным с u вершинам
if (!visited[v]) //проверяем, не находились ли мы ранее в выбранной вершине
dfs(v);
}
int main()
{
... //задание графа G с количеством вершин n.
visited.assign(n, false); //в начале все вершины в графе не пройденные
for (int i = 0; i < n; ++i) //проходим по всем вершинам графа...
if (!visited[i]) //...не забыв проверить, были мы уже в очередной вершине или нет
dfs(i);
return 0;
}
