Собственно есть 3 версии данной задачи
http://www.e-olimp.com.ua/problems/1726 (1)
http://www.e-olimp.com.ua/problems/1727 (2)
http://www.e-olimp.com.ua/problems/1728 (3)
Рассмотрим решение (1). Используем дейкстру, но будем искать не минимальное расстояние до вершины v, а минимальную сумму, которую придется потратить в худшем случае, добравшись до вершины v, заплатив 1 раз. Переход будет таким: если мы находимся в вершине from и хотим сделать переход в вершину to, то dp[to] = min(dp[to], max(dp[from], rib[from][to])) Где rib[from][to] ребро между этими двумя вершинами. Это решение заходит.
Задача (2). Сделаем тоже самое, что и в (1). Сохраним в dp1. dp2[v] будет хранить минимальную сумму, которую придется потратить в худшем случае, добравшись до вершины v, заплатив 2 раза. Переход будет таким: если мы находимся в вершине from и хотим сделать переход в вершину to, то dp2[to] = min(dp2[to], max(dp2[from], dp1[from] + rib[from][to])) Таким образом, выбираем что хуже, если мы уже в вершине from: если мы уже заплатили 2 раза или если заплатили 1 раз и на текущем ребре заплатим второй. Отдельно надо рассмотреть случай, если до конечной вершины можно добраться ровно за 1 ход. Такое решение не проходит все тесты. Не могу понять в чем проблема. В идее или реализации?
Если бы это было верно, можно было бы обобщить и на (3).
Идея автора изначального сообщения выглядит не очень верно, похоже, она будет где-то выбирать место сбора за стражей.
Задача в версии 3 великолепна, спасибо Ивану Метельскому (ivan.metelsky)
Похоже, решение я придумал, но я бы не хотел писать его на живом контесте :)
Понятно, что случай пути длины 1 и 2 можно рассмотреть за O(M) отдельно. Кроме того, нужно сделать все веса ребер различными.
Рассмотрим некоторое ребро u->v. Будем считать, что на этом ребре у нас возьмут пошлину, т.е. оно одно из худших на пути, причем вдоль этого пути оно второе из таких. Тогда на пути A->u и v->B должно быть не более одного ребра длиннее u->v. Таким образом, задача сведена к обработке двух запросов (для В симметрично):
1) Изменить флаг для ребра с "запрещено" на "разрешено".
2) Найти путь с минимальным максимальным весом ребра, использующий не более одного запрещенного ребра, от А до u.
Причем гарантируется, что вес любого разрешенного ребра не больше веса любого запрещенного. (После этого понятно - обрабатываем ребра в порядке возрастания веса и т.д.)
Запросы можно выполнять так. Будем хранить связные компоненты разрешенных ребер (например, при помощи disjoint-set, причем с модификацией, позволяющей за размер компоненты ее перечислить - это можно сделать, храня весь список компоненты вместо ранга и объединяя с перекидыванием меньшей). Далее, если A и u в одной такой компоненте, то ответ - решение задачи (1) для (A,u), и он предпросчитан. Если они в разной, то единственный запрещенный переход является худшим. Осталось найти его длину. Для этого будем хранить расстояние от компоненты, содержащей А, до всех всех остальных компонент, или бесконечность, если для этого потребуется два и более запрещенных перехода. Обрабатывать это будем так:
1) Соединяются две компоненты с расстоянием бесконечность - игнорировать
2) Соединяются две компоненты, расстояние до одной не бесконечность, а до другой бесконечность. Весь состав "бесконечной" компоненты необходимо проверить на предмет улучшения расстояния "конечной".
3) Соединяются две компоненты, расстояние до обеих конечно. Ответ новой - минимум из бывших ответов.
4) Группа соединяется с содержащей А. Весь состав присоединяющейся группы необходимо проверить на предмет улучшения до некоторого соседа А.
Update. Здесь пропущен важный случай. Необходимо также проверять в главном цикле, что не происходит ситуации, что два ребра пути v->B больше, чем самое длинное на пути A->u. Для этого в этом пункте необходимо выбросить из главного цикла все будущие ребра, ведущие из присоединяемой компоненты в вершину, такую, что из В до нее нельзя добраться, используя не более одного "запрещенного" ребра.
Заметим, что в сумме проверки 2) и 4) потребуют O(M) времени (каждая вершина пройдет эту фазу не более 1 раза). Проверки 1) и 3) выполняются за О(1).
Ответом на запрос здесь будет расстояние от компоненты, содержащей A, до компоненты, содержащей u.
Итоговая сложность O(M*log(M))
Как-то так...
А, немножко не так понял.
Эта версия некорректна для алгоритма Дейкстры. Релаксация ребра меняет расстояния не только до самой вершины.