Загрузил rodzher.zet

Практика по алгоритмам Поиск в ширину, Дийкстра

Реклама
Первый курс, весенний семестр 2017/18
Практика по алгоритмам #5
BFS, Dijkstra
14 февраля
Собрано 29 марта 2020 г. в 16:48
Содержание
1. BFS, Dijkstra
1
2. Разбор задач практики
2
3. Домашнее задание
3.1. Обязательная часть . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.2. Дополнительная часть . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5
5
6
4. Разбор домашнего задания
4.1. Обязательная часть . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.2. Дополнительная часть . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
7
7
9
Алгоритмы, весна 2019/20
Практика #5. BFS, Dijkstra.
BFS, Dijkstra
3
1. Матрица расстояний за 𝒪( 𝑉𝑤 )
В орграфе с единичными весами.
2. Модификации bfs
a) 1-2-bfs, веса вещественные.
b) 0-1-bfs, веса вещественные.
3. Ускорение 1-𝑘-bfs
a) 𝒪(𝐸 log 𝑘)
b) 𝒪(𝐸 log log(𝑉 𝑘))
c) (*) 𝒪(𝐸 log log 𝑘)
4. Ускорение Дейкстры
(a) 𝒪(𝐸 + 𝑉 log 𝑉 ), (b) 𝒪(𝐸 log log 𝐶).
5. Флойд и битовое сжатие
3
Найдите транзитивное замыкание графа за 𝒪( 𝑉𝑤 ).
6. Двусторонний Дейкстра
Ищем кратчайший путь 𝑎
𝑏 так: запускаем Дейкстру параллельно из 𝑎 вперед (массив 𝑑1 )
и из 𝑏 назад (массив 𝑑2 ). Когда одна из Дейкстр меняет расстояние до 𝑣, она обновляет ответ
величиной 𝑑1 [𝑣] + 𝑑2 [𝑣]. Доказать корректность, если алгоритм останавливается, когда:
a) нашлась вершина, обработанная обеими Дейкстрами (найдены верные 𝑑1 и 𝑑2 );
b) текущий ответ min𝑣 (𝑑1 [𝑣] + 𝑑2 [𝑣]) 6 𝑄1 . min() + 𝑄2 . min().
7. Число кратчайших путей
Дан взвешенный орграф с положительными весами и вершина 𝑠, нужно для каждой вершины 𝑣 найти число кратчайших путей из 𝑣 в 𝑠. 𝒪(𝐸 log 𝑉 ). А если есть нулевые веса?
8. Кратчайший путь по выделенным вершинам
Дан взвешенный орграф с положительными весами. Найти кратчайший путь из 𝑠 в 𝑡, проходящий по всем 𝑘 6 10 выделенным вершинам.
9. Обобщение Дейкстры
На каких функциях кроме суммы работает алгоритм Дейкстры?
10. Максимальный корабль
Даны две паралелльных прямых (река). В реке есть 𝑛 островов (точек). Нужно провести по
реке круглый корабль максимального радиуса 𝑅 так, чтобы он не задел ни одного осторова.
Найти только число 𝑅 за 𝒪(𝑛2 log 𝑀 ). А за 𝒪(𝑛2 )?
11. (*) Topsort в плотных графах
2
Найдите топологическую сортировку дага за 𝒪( 𝑉𝑤 ).
12. (*) Веса-пары: кратчайший по 𝑦 путь с ограничением на 𝑥
Есть ограф, на ребрах этого орграфа написаны
целых чисел ⟨𝑥𝑒 , 𝑦𝑒 ⟩.
∑︀ пары положительных
∑︀
Нужно найти путь path из 𝑠 в 𝑡 такой, что
𝑥𝑒 6 𝐴, а
𝑦𝑒 → min. 𝒪(𝑉 + 𝐸 · 𝐴).
𝑒∈path
𝑒∈path
13. (*) Плохая функция для 𝐴*
Придумать функцию оценки 𝑓 для 𝐴* , на которой он будет работать дольше Дейкстры.
∃𝑓 : 𝐴* работает экспоненциально долго.
1/10
Закончилась практика?
Отнеси лист на второй этаж в эко-мусорку
Алгоритмы, весна 2019/20
Практика #5. BFS, Dijkstra.
Разбор задач практики
3
1. Матрица расстояний за 𝒪( 𝑉𝑤 )
2
bfs за 𝒪( 𝑉𝑤 ) из каждой вершины.
Поддерживаем bitset unvisited еще не посещенных вершин и bitset current вершин на
текущем расстоянии 𝑑.
Пусть в current 𝑛𝑑 единиц. Чтобы получить bitset вершин на расстоянии 𝑑 + 1, перебираем
единицы из current (за 𝑛𝑑 + 𝑉𝑤 ), получаем номера вершин 𝑣, считаем next – OR bitset-ов
𝑔[𝑣] их соседей (за 𝑛𝑑 𝑉𝑤 ). 𝑑 + 1-й слой – next & unvisited.
∑︀
2
Итого операций 𝑑 𝑛𝑑 𝑉𝑤 + 𝒪( 𝑉𝑤 ) · MAXDIST = 𝒪( 𝑉𝑤 ).
2. Модификации bfs
a) 1-2-bfs, веса вещественные.
Три очереди: вершины на расстояниях [𝑑, 𝑑 + 1), [𝑑 + 1, 𝑑 + 2), [𝑑 + 2, 𝑑 + 3).
Когда вынимаем из первой очереди вершину на расстоянии 𝑑′ и смотрим из нее на ребро
веса 𝑤, будет 𝑑′ + 𝑤 < 𝑑 + 3. По 𝑑′ + 𝑤 поймем, в какую очередь ее положить.
Корректность, как у 1-𝑘-bfs. Инвариант: на текущий момент верно посчитаны расстояния
для всех вершин на расстоянии < 𝑑 + 1.
Когда опустела [𝑑, 𝑑 + 1) очередь, инварант верен уже для следующей очереди: если до
вершины расстояние [𝑑 + 1, 𝑑 + 2), то до предыдущей на кратчайшем пути оно [𝑑 − 1, 𝑑 + 1),
такие уже обработаны.
b) 0-1-bfs, веса вещественные. Это эквивалетно задаче с произвольными весами.
Были 0-1 веса ⇒ делим все веса на минимальный, получили сколь угодно большие веса.
Были произвольные веса ⇒ делим все веса на максимальный, получили веса 0-1.
В общем, не надо это решать bsf-ом, надо Дейкстрой.
3. Ускорение 1-𝑘-bfs
Напомним, в 1-𝑘-bfs мы обрабатываем каждое ребро один раз, а вот для поиска следующей
вершины нам нужна непустая очередь с минимальным расстоянием, на ее поиск может уйти
𝑘 операций, итого 𝒪(𝐸 + 𝑘𝑉 ).
a) 𝒪(𝐸 log 𝑘): храним номера непустых очередей в бинарной куче.
Время 𝑉 · ExtractMin + 𝐸 · Add = 𝒪(𝐸 log 𝑘).
b) 𝒪(𝐸 log log(𝑉 𝑘)): храним номера непустых очередей в van Emde Boas tree (все операции
за 𝒪(log log 𝐶)). Номера очередей: [0, MAXDIST], MAXDIST 6 𝑉 𝑘.
c) 𝒪(𝐸 log log 𝑘): храним два van Emde Boas tree: одно для расстояний [𝑘𝑖, 𝑘(𝑖 + 1)), другое
для [𝑘(𝑖 + 1), 𝑘(𝑖 + 2)].
В каждом храним номера от 0 до 𝑘, так что log log 𝑘.
4. Ускорение Дейкстры
Напомним, Дейкстра работает за 𝑉 · ExtractMin + 𝐸 · DecreaseKey.
a) 𝒪(𝐸 + 𝑉 log 𝑉 ) – куча Фибоначчи.
b) 𝒪(𝐸 log log 𝐶) – van Emde Boas.
2/10
Алгоритмы, весна 2019/20
Практика #5. BFS, Dijkstra.
5. Флойд и битовое сжатие
Как выглядит обычный флойд для транзитивного замыкания?
for k = 0..n-1:
for i = 0..n-1:
for j = 0..n-1:
a[i][j] |= (a[i][k] and a[k][j])
Перепишем код, так чтобы использовать битовое сжатие (a[i] это теперь битсет).
for k = 0..n-1:
for i = 0..n-1:
if (a[i][k])
a[i] |= a[k] // a[i][j] |= (a[i][k] and a[k][j])
6. Двусторонний Дейкстра
Допустим, есть путь короче, чем мы нашли. Тогда он < 𝑐1 + 𝑐2 , где
a) 𝑐1 = 𝑑1 [𝑣], 𝑐2 = 𝑑2 [𝑣], где 𝑣 – обработанная обеими сторонами вершина
b) 𝑐1 = 𝑄1 . min(), 𝑐2 = 𝑄2 . min()
На этом пути есть последняя вершина 𝑣 : 𝑑1 [𝑣] < 𝑐1 , за ней идет 𝑢 : 𝑑1 [𝑢] > 𝑐1 .
Раз длина пути < 𝑐1 + 𝑐2 , то 𝑑2 [𝑢] < 𝑐2 . Тогда первый Дейкстра уже обработал 𝑣, второй 𝑢.
Значит, длина пути равна 𝑑1 [𝑣] + 𝑤(𝑣, 𝑢) + 𝑑2 [𝑢].
Кто-то из 𝑣 и 𝑢 был обработан раньше, пусть 𝑣.
Когда второй Дейкстра обработал 𝑢, он обновил величину 𝑑2 [𝑣] величиной 𝑑2 [𝑢] + 𝑤(𝑣, 𝑢),
затем обновил ответ величиной 𝑑1 [𝑣] + 𝑑2 [𝑣] 6 𝑑1 [𝑣] + 𝑤(𝑣, 𝑢) + 𝑑2 [𝑢].
То есть мы всё-таки нашли путь не хуже, чем этот.
7. Число кратчайших путей
Решение #1: запускаем Дейкстру, оставляем только ориентированные ребра (𝑎, 𝑏, 𝑤) : 𝑑[𝑎] +
𝑤 = 𝑑[𝑏].
Получили так называемый «граф кратчайших путей».
∀𝑒 : 𝑤[𝑒] > 0 ⇒ граф кратчайших путей ацикличен. Считаем на нем динамикой число путей
из 𝑠 во все 𝑣.
Если есть нулевые ребра, будут нулевые циклы, по которым можно бесконечно крутиться.
Решение #2: по ходу Дейкстры считаем еще и count[𝑣] – число путей длины 𝑑[𝑣].
8. Кратчайший путь по выделенным вершинам
Запустим Дейкстру из 𝑘 фиксированных вершин и начальной.
Теперь сделаем орграф только из фиксированных вершин и начальной с конечной. Вес ребер
в нем равен кратчайшему пути в исходном графе.
Получили задачу коммивояжёра на 𝑘 + 2 вершинах. 𝒪(𝑘 · Dijkstra + 2𝑘 𝑘 2 ).
9. Обобщение Дейкстры
Подходят такие функции от пути, что:
∀ префикс ∀ пути имеет ответ не хуже, чем весь путь;
∀ префикс оптимального пути оптимален.
Примеры:
• Произведение весов, все веса > 1. Можно прологарифмировать веса, тогда произведение
перейдёт в сумму, а 1 перейдёт в 0.
3/10
Алгоритмы, весна 2019/20
Практика #5. BFS, Dijkstra.
• Максимальное ребро на пути.
• Минимальное ребро на пути, мы хотим максимизировать его.
10. Максимальный корабль
Построим граф с 𝑛 + 2 вершинами – два берега и острова. Вес ребра между вершинами –
евклидово расстояние на плоскости.
Максимальный радиус 𝑅 равен длине кратчайшего пути от одного берега до другого, где
вес пути – максимум весов ребер на пути.
Способы поиска пути: бинпоиск по ответу + dfs за 𝒪(𝑛2 log 𝑀 ) или Дейкстра за 𝒪(𝑛2 ). Еще
можо сортировкой ребер + СНМ за 𝒪(𝑛2 log 𝑛). А еще в том семестре научились делать это за
𝒪(𝑉 + 𝐸) = 𝒪(𝑛2 ) с помощью нахождения медианы за линию.
Корректность. Пусть мы можем провести корабль радиуса 𝑅, тогда заменим его на точку, а
все объекты-препятствия раздуем на 𝑅. Если раздутые объекты-препятствия пересекаются,
проведём между ними ребро. Корабль-точку можно провести по реке ⇔ разные берега лежат
в разных компонентах связности.
11. (*) Topsort в плотных графах
2
dfs за 𝒪( 𝑉𝑤 ).
Обрабатываем вершину v. Помечаем ее посещенной в bitset unvisited. Пока g[v] &
unvisited != 0, делаем g[v] &= unvisited и вызываемся рекурсивно от младшей единицы
в g[v].
На каждом ребре дерева dfs делаем AND bitset-ов и ищем младшую единицу в bitset. И
2
то, и то за 𝒪( 𝑉𝑤 ), а ребер в дереве dfs (𝑉 − 1). Итого 𝒪( 𝑉𝑤 ).
12. (*) Веса-пары: кратчайший по 𝑦 путь с ограничением на 𝑥
𝑑[𝑣, 𝑎] – кратчайший путь из 𝑠 в 𝑣, на котором сумма 𝑥𝑒 6 𝑎.
Раз все 𝑎𝑒 > 0, можно пересчитывать 𝑑[𝑣, 𝑎] = min 𝑑[𝑢, 𝑎 − 𝑥𝑒 ] в порядке увеличения 𝑎.
𝑒=(𝑢,𝑣)
Суммарное число переходов – 𝒪(𝐸 · 𝐴).
13. (*) Плохая функция для 𝐴*
Пусть кратчайший путь из 𝑛 в 1 равен 𝑛 → 𝑛 − 1 → . . . → 2 → 1, веса ребер 1.
Также между всеми парами вершин есть ребро веса 𝑛.
Возьмем 𝑓𝑣 = 𝑛𝑣 . Тогда 𝐴* будет работать за 2𝑛 , т.к. сперва пойдёт не в 𝑛 − 1, а в 1...
𝑇 (𝑘) – время работы от вершины 𝑘 до конца. 𝑇 (𝑘) = 1 + 𝑇 (1) + 𝑇 (2) + . . . + 𝑇 (𝑘 − 1) = 2𝑘−1 .
4/10
Алгоритмы, весна 2019/20
Практика #5. BFS, Dijkstra.
Домашнее задание
3.1. Обязательная часть
1. (2) Модификации bfs
a) (1) 𝑘-2𝑘-bfs, веса вещественные.
b) (1) 𝑘-2𝑘-bfs, веса целые, хотим делать только целочисленные операции.
2. (2) Ускорение Дейкстры
𝒪(𝑚 log𝑚/𝑛 𝑛).
3. (2) Число кратчайших путей
Дан невзвешенный неорграф и два множества вершин – 𝐴 и 𝐵, 𝐴 ∩ 𝐵 = ∅. Найти (длину
кратчайшего пути из 𝐴 в 𝐵) и (количество кратчайших путей из 𝐴 в 𝐵) mod 109 . 𝒪(𝑛 + 𝑚).
(+2) балла за случай 𝐴 = 𝐵 (min𝑢,𝑣∈𝐴,𝑢̸=𝑣 𝑑(𝑢, 𝑣)).
4. (2) Предподсчет
Дан неорграф. Сделайте предподсчет за 𝒪(𝑛3 ), чтобы за 𝒪(1) отвечать запрос ⟨𝑎, 𝑏, 𝑒⟩ –
существует ли кратчайший путь из 𝑎 в 𝑏, проходящий через ребро 𝑒?
5. (2) Путь не весь через 𝐴
Даны взвешенный неорграф, веса положительны. Дано множество вершин 𝐴 и выделенная
вершина 𝑠. Для каждой вершины графа 𝑣 проверить, есть ли кратчайший путь из 𝑠 в 𝑣,
проходящий не только по вершинам из 𝐴? 𝒪(𝑚 log 𝑛).
(+1) балл за случай неотрицательных весов.
6. (3) Обмен местами
Есть невзвешенный орграф. Для каждой пары вершин 𝑎, 𝑏 определена функция расстояния
𝑓 (𝑎, 𝑏). Вася и Петя стоят в вершинах 𝑣 и 𝑢 соответственно и хотят поменяться местам, не
оказываясь ни в какой момент времени ближе, чем на расстоянии 𝑑. За ход любой один
из них переходит в смежную вершину. За какое минимальное число ходов они могут это
сделать? 𝒪(𝑛𝑚). (Частичный балл за 𝒪(𝑛2 𝑚))
5/10
Алгоритмы, весна 2019/20
Практика #5. BFS, Dijkstra.
3.2. Дополнительная часть
1. (3) Сумма двух максимальных ребер
Есть взвешенный неограф. Найти путь из 𝑠 в 𝑡 такой, что сумма двух максимальных ребер
на пути минимальна. 𝒪((𝑛 + 𝑚) · poly(log 𝑛)).
2. (5) Сумма трёх максимальных ребер
Такая же, как предыдущая, но три ребра.
3. (3) Антитест для bfs
Постройте матрицу 𝑛 × 𝑛, состояющую из стенок и пустых клеток, на которой при выполнении bfs-а из правого нижнего угла размер очереди будет 𝜔(𝑛). Ходить можно между
вершинами смежными по стороне.
4. (4) Запросы с уменьшением весов
Дан взвешенный граф с положительными ребрами, в нем выделены вершины 𝑎 и 𝑏. Запрос
Get(𝑠) – минимальная длина пути из 𝑎 в 𝑏, причем весом ребра 𝑒 считается min(𝑠, 𝑤𝑒 ). 𝑠 > 0.
Научиться быстрее, чем «𝑘 раз запустить Дейкстру» обработать 𝑘 запросов Get(𝑠).
6/10
Алгоритмы, весна 2019/20
Практика #5. BFS, Dijkstra.
Разбор домашнего задания
4.1. Обязательная часть
1. Модификации bfs
𝑘-2𝑘-bfs. Можно поделить все веса на 𝑘 и получить 1-2-bfs.
А можно не делить явно, а поделить мысленно, и сделать то же, что в 1-2-bfs. То есть будут
очереди для расстояний [𝑑, 𝑑 + 𝑘), [𝑑 + 𝑘, 𝑑 + 2𝑘), [𝑑 + 2𝑘, 𝑑 + 3𝑘).
2. Ускорение Дейкстры
Дейкстра на 𝑑-куче работает за 𝑛𝑑 log𝑑 𝑛 + 𝑚 log𝑑 𝑛. Берем 𝑑 =
𝑚
.
𝑛
3. Число кратчайших путей
Помещаем в очередь все вершины из 𝐴, ставим им расстояние 0. Делаем bfs.
Находим вершину из 𝐵 с кратчайшим расстоянием 𝑑.
Строим граф кратчайших путей. Считаем динамикой, сколько путей длины 𝑑 в вершины из
𝐵.
Если 𝐴 = 𝐵, пускаем bfs из всех вершин 𝐴, запоминая также from𝑣 – из какой вершины 𝐴
мы впервые пришли в 𝑣.
Пусть при обработке слоя 𝑑 впервые случилось, что из какой-то 𝑣 смотрим в такую посещенную 𝑢, что from𝑣 ̸= from𝑢 .
Либо 𝑑𝑢 = 𝑑𝑣 , тогда нашли кратчайший нечетный путь, либо 𝑑𝑢 = 𝑑𝑣 + 1, тогда четный.
Важно остановиться не сразу, а закончить слой, ибо сначала может встретиться вершина на
расстоянии 𝑑 + 1, и только потом на 𝑑.
Если путь нечетный, то ответ – сумма count𝑣 · count𝑢 по всем ребрам (𝑣, 𝑢) : from𝑣 ̸=
from𝑢 , 𝑑𝑢 = 𝑑𝑣 = 𝑑.
Если четный, смотрим на эти 𝑢 на расстоянии 𝑑 + 1. За 𝒪(deg𝑢 ) считаем count𝑢,𝑎 для всех
𝑎 ∈ 𝐴, из которых можно дойти до 𝑢 за 𝑑 + 1. Ответ – сумма ∑︀
попарных
произведений
∑︀
∑︀
( 𝑎𝑖 )2 − 𝑎2𝑖
.
count𝑢,𝑎 · count𝑢,𝑏 . Ее тоже можно посчитать за 𝒪(deg𝑢 ):
𝑎𝑖 𝑎𝑗 =
2
4. Предподсчет
Нашли 𝑑[𝑣][𝑢] Флойдом за 𝒪(𝑛3 ).
Из 𝑎 в 𝑏 есть кратчайший путь, проходящий через 𝑒 = (𝑥, 𝑦) ⇔ 𝑑[𝑎][𝑥] + 𝑤𝑒 + 𝑑[𝑦][𝑏] = 𝑑[𝑎][𝑏].
Надо проверить оба направления ребра.
5. Путь не весь через 𝐴
𝑓 [𝑣] – есть ли путь с вершиной не из 𝐴. Дейкстра.
Когда обрабатываем вершину 𝑣, если она не из 𝐴, то 𝑓 [𝑣] = 1.
Когда пытаемся релаксировать ребро 𝑒 = (𝑣, 𝑢), если 𝑑[𝑣] + 𝑤𝑒 6 𝑑[𝑢], то 𝑓 [𝑢] | = 𝑓 [𝑣].
Еще можно явно построить граф кратчайших путей, и сделать dfs с такой же обработкой
вершин.
Если есть нулевые ребра, строим граф кратчайших путей, конденсируем его.
Если какая-то вершина 𝑣 – это сжатая компонента, содержащая вершины не из 𝐴, то сразу
𝑓 [𝑣] = 1. Остальное то же самое.
Другое решение: смотрим на кратчайшие пути в графе (𝑣, 𝑓 𝑙𝑎𝑔), где 𝑓 𝑙𝑎𝑔 это была ли уже
хотя бы одна вершина не из 𝐴.
7/10
Алгоритмы, весна 2019/20
Практика #5. BFS, Dijkstra.
6. Обмен местами
Строим новый граф.
Вершины нового графа – пары вершин исходного графа (𝑎, 𝑏), у которых 𝑓 (𝑎, 𝑏) 6 𝑑.
(𝑎, 𝑏) → (𝑐, 𝑏); (𝑎, 𝑑), где ребра 𝑎 → 𝑐 и 𝑏 → 𝑑 есть в исходном графе.
bfs по новому графу.
Вершин в новом графе 𝑛2 , ребер 2𝑛𝑚: каждое ребро 𝑢 → 𝑣 старого графа превращается в
2𝑛 ребер нового – (𝑎, 𝑢) → (𝑎, 𝑣), (𝑢, 𝑏) → (𝑣, 𝑏).
8/10
Алгоритмы, весна 2019/20
Практика #5. BFS, Dijkstra.
4.2. Дополнительная часть
1. Сумма двух максимальных ребер
Просто Дейкстрой не решается, т.к. такую функцию не умеем пересчитывать при прохождении по ребру вперёд.
Запустим Дейкстру от 𝑠, получим расстояния max𝑠 [𝑣] и Дейкстру от 𝑡, получим расстояния
max𝑡 [𝑣]. Обе Дейкстры минимизируют максимальное ребро на пути.
В ответе есть максимальное ребро 𝑒 : 𝑎 → 𝑏, переберём его.
Если max(max𝑠 [𝑎], max𝑡 [𝑏]) 6 𝑤𝑒 , то 𝑤𝑒 и правда может быть максимумом на пути, обновляем
ответ значением 𝑤𝑒 + max(max𝑠 [𝑎], max𝑡 [𝑏]).
2. Сумма трёх максимальных ребер
Проходим рёбра в порядке возрастания веса. Храним образованные компноненты в СНМ.
Рассмотрим путь-ответ и его 3 тяжелейших ребра 𝑥 6 𝑦 6 𝑧.
Рассмотрим момент перед добавлением 𝑥. Сейчас путь разбит на 4 куска 𝐶1 , 𝐶2 , 𝐶3 , 𝐶4 .
𝑠 ∈ 𝐶1 , 𝑡 ∈ 𝐶4 .
Если 𝑥 посередине, то 𝐶2 и 𝐶3 сейчас «видны» из 𝐶1 и 𝐶4 по еще не добавленным ребрам.
Если 𝑥 с краю (пусть у 𝑠, иначе аналогично), то после слияния 𝐶1 и 𝐶2 станет «виден» с
обеих сторон 𝐶3 .
Как воспользоваться «видимостью»? Для каждой компоненты храним min ребро, по которому она видна из 𝐶1 , и то же для 𝐶4 .
Эти величины надо обновлять при слиянии двух компонент. Также при добавлении вершин
в 𝐶1 и 𝐶4 пересчитывать их просто обходом соседей каждой добавленной вершины.
Итого Sort(𝐸) + 𝐸 · DSU(𝑉 ).
3. Антитест для bfs
###########
#
###
#
#
###
#
#
###
#
##C#####C##
##
##
##C## ##C##
#
# #
#
#
# #
#
#
# #
#
#####B#####
A
#####
Стартуя из точки 𝐴, получаем один тест со стартом из 𝐵 внутрь большого квадрата.
Из 𝐵 мы дойдём до всех 4 точек 𝐶 за одно время и получим 4 меньших квадрата. Рекурсивно
построим в них такую же конструкцию.
Итого 𝑄(𝑛) = 4𝑄( 𝑛−5
) = Θ(𝑛2 ) – размер очереди в конце bfs.
2
4. Запросы с уменьшением весов
Задача #1: Get(a,b,s). Научимся быстро делать полный предподсчёт.
9/10
Алгоритмы, весна 2019/20
Практика #5. BFS, Dijkstra.
𝑑[𝑎, 𝑏] – кусочно-линейная функция от 𝑥, длина пути от 𝑎 до 𝑏.
В ней < 𝑛 изгибов, т.к. угол наклона – число рёбер длины > 𝑥 в пути.
Насчитаем все 𝑑[𝑎, 𝑏] Флойдом за 𝒪(𝑛3 · 𝑛), отвечать на каждый запрос будем за 𝒪(1).
Задача #2: Get(s). Расстояние в каждом запросе от 𝑎 до 𝑏. Дейкстрой такую кусочнолинейную функцию обновлять нельзя. Можно Форд-Беллманом за 𝒪(𝑛𝑚), итого 𝒪(𝑛𝑚 · 𝑛)
Другое решение. Рассмотрим упорядоченный массив различных весов рёбер: 𝑤0 < 𝑤1 < . . ..
Зафиксируем промежуток [𝑤𝑖 , 𝑤𝑖+1 ) для 𝑥.
Запустим Дейкстру на графе ⟨𝑣, 𝑡⟩, где 𝑡 – количесто рёбер, больших 𝑤𝑖 , на пути.
Время работы 𝒪(𝑚 · Dijkstra(𝑛2 , 𝑛𝑚)).
10/10
Скачать