
- •Граф. Ориентированный граф. Представления графа. Обход графа в глубину и в ширину.
- •Топологическая сортировка. Подсчет числа путей в орграфе.
- •Сильно связные компоненты.
- •Поиск кратчайших путей в графе. Алгоритм Флойда. Алгоритм Дейкстры. Алгоритм Форда-Беллмана.
- •Алгоритм a*. Эвристики.
- •Минимальное остовное дерево. Алгоритм Прима. Биномиальная куча.
- •Амортизационная стоимость. Фибоначчиева куча. Амортизационная стоимость (анализ)
- •Метод потенциалов
- •Фибоначчиева Куча
- •Структура
- •Время работы
- •Система непересекающихся множеств. Алгоритм Крускала.
- •Наивная реализация
- •Эвристика сжатия пути
- •Эвристика объединения по рангу
- •Потоки, Форда-Фалкерсона.
- •Декартово дерево
- •Дерево Фенвика. Дерево отрезков и динамическое программирование для rmq.
- •Сведение rmq к lca и наоборот.
- •Препроцессинг
- •Ответы на запросы
- •Алгоритм
- •Доказательство
- •Сложность
- •Алгоритм
- •Минимум внутри блока
- •Результат
- •Поиск нескольких минимумов на отрезке. Задача поиска подстрок. Алгоритм Рабина-Карпа. Конечный автомат. Алгоритм Бойера-Мура.
- •Метод хеширования
- •Алгоритм
- •Время работы
- •Алгоритм Бойера-Мура
- •Поиск со звездочками. Алгоритм Кнута-Морриса-Пратта.
- •Время работы
- •Алгоритм Ахо-Корасика.
- •Дерево ключевых слов (бор)
- •Пример дерева ключевых слов (бора)
- •Построение бора
- •Поиск строки в бору
- •Автомат Ахо-Корасик
- •Суффиксное дерево, Алгоритм Укконена.
- •2. Квадратичный алгоритм
- •3. Линейный алгоритм
- •Суффиксный массив.
- •Наивный алгоритм поиска
- •Алгоритм, использующий префиксы циклических сдвигов
- •Исключения
- •Шаблоны
- •Stl: итераторы
- •Сортировка и поиск в stl. Алгоритмы stl
- •Куча в stl. Алгоритмы stl.
- •Ассоциативный массив. Интерфейс, варианты реализации.
Граф. Ориентированный граф. Представления графа. Обход графа в глубину и в ширину.
Граф – упорядоченная пара множеств E (ребра) и V (вершины) <V, E>. E – множество 2-ух элементных подмножеств V и V – не пусто.
Дерево – ацикличный связный граф.
Ориентированный граф – граф, ребрам которого присвоено направление (ребро (1,2) != ребро (2,1), в отличие от неориентированного графа).
Граф разреженный, если |E| << |V^2|
Представления графа:
Матрица смежности:
Один из самых распространённых способов хранения графа - матрица смежности. Она представляет собой двумерный массив. Если в клетке i, j (i – строка, j - столбец) установлено значение пусто (как правило, это очень большая величина или величина, которой заведомо не может равняться вес ребра), то дуги, начинающейся в вершине i и кончающейся в вершине j, нет. Иначе дуга есть. Если она есть, то в соответствующую ячейку записывают ее вес. Если граф не взвешенный, то вес дуги считается равным единице. Минус: много памяти (медленно работает и много памяти на разреженных графах)
Плюс: можно узнать за const есть ли ребро между 2 вершинами
Список дуг:
Vector / list<E>
Следующий тип хранения графа в памяти компьютера - список дуг. Чаще всего это двумерный массив размером 3*E, в первой строке которого хранится информация, из какой вершины начинается дуга, во второй - в какой кончается, а в третьей строке - вес дуги (Или просто храним в ячейке вектора / листа структурки edge).
Как видно, этот способ, в отличие от матрицы смежности, хранит информацию о номере дуги. Также ясно, что этот способ нам выгоден, если чаще всего нам нужно будет узнать что-то (вес, вершины начала или конца) о i-ой дуге. Однако, такие задачи в практическом программировании встречаются довольно редко.
Списки смежности:
Vector < list < V> >.
В i-ом элементе массива – лист из таких вершин j, что существует ребро (i,j)
Если граф разреженный – лучше этот способ (экономия памяти).
DFS (поиск в глубину)
Сложность: O(|E| + |V|) – Если храним как списки смежности – иначе O(V^2)
Присваиваем всем вершинам белый цвет
Берем какую-то белую вершину
Красим ее в серый
Если есть белый потомок, переходим в него и goto 3,
Если нет, то красим ее в черный и переходим к родителю goto 3a
Если нет родителя и еще остались белые вершины, то goto 2
Если никого не осталось - конец алгоритма.
Теорема.
Граф G ацикличный DFS не найдет обратных ребер.
От противного. Пусть существует обратное ребро. Пусть (U,V) – обратное ребро. Значит V - предок вершины U в лесу поиска в глубину, значит в графе G есть путь, который из V в U ведет => (U,V) завершает цикл, значит G не ацикличный. Противоречие
Существует цикл С, где V-его первая вершина. Пусть (U,V) – ребро из цикла С. В момент времени d[v] (когда вошли в v) все остальные вершины в С – белые. Теперь U стал потомком V в DFS (из Т. О белом пути). У нас есть ребро (V,U) и получилось, что оно обратное к (U,V) – противоречие.
Всего 3 случая DFS:
[d[u], f[u]], [d[v][f[v]] – не пересекаются
[d[u], f[u]] в [d[v][f[v]] – U – потомок V
Наоборот 2
Теорема об отрезках.
А) d[u]<d[v]
1) d[v]<f[u] – значит U серая (V – потомок вершины U). Значит все ребра, выходящие из V исследуются до возвращения в U. Значит f[V]<f[U]
2) d[v]>f[u] Значит d[u]<f[u]<d[v]<f[v]
Отрезки не пересекаются.
Следствие из Теоремы.
V является потомком U, если выполнено неравенство. d[u]<d[v]<f[v]<f[u].
Теорема о белом пути.
В лесу DFS v является потомком вершины u В момент времени d[u] v достижима из u по пути только из белых вершин.
V является потомком U. Возьмем произвольную вершину на пути из U в V (W), При этом W – потомок U => d[U]<d[W] => В момент d[U] – W белая
В d[U] вершина V достижима из U по белому пути, но пусть V не является потомком U Возьмем W – предшественника V. Тогда W – потомок U и f[W]<=f[U] (по следствию из теоремы отрезков). V открыта после U, но до завершения W, значит d[U]<d[V]<f[W]<f[U]. d[V] зажато между началом обработки U и концом. Значит f[V]тоже в этом интервале, значит d[U]<d[V]<f[V]<f[U]. Значит V – потомок U
BFS (обход в ширину)
Сложность: O(|E| + |V|)
Берем какую-то вершину
Добавляем ее в очередь (помечаем как пройденную)
Пока очередь не пуста
Достаем первую вершину
Добавляем в очередь все ее непройденные потомки
Goto 3