Задача

Журнал сравнений

сортировка порядок зависимостей граф

Программа сортировала n различных чисел и записывала в журнал каждое сравнение, которое делала: «число a меньше числа b». Числа пронумерованы от 1 до n, сами значения потерялись, и часть записей журнала тоже. Восстанавливается ли по оставшимся записям порядок всех n чисел?

Если да, выведите YES и номера чисел по возрастанию. Если нет — NO и номера двух чисел, порядок которых по журналу установить нельзя: из записей не следует, что одно меньше другого, даже через цепочку «a < c, c < b». Подходящих пар может быть несколько — годится любая.

Журналы в тестах настоящие: так сравнивали сортировка слиянием, sorted из Python, пирамидальная и быстрая сортировки, когда упорядочивали население и широты городов мира (GeoNames). В некоторых тестах часть записей стёрта.

В первом примере 3 < 1, 1 < 4 и 4 < 2: порядок 3, 1, 4, 2 записан целиком. Во втором известно, что 3 меньше и 1, и 4, а оба они меньше 2, но кто из 1 и 4 меньше — не записано.

Вход

В первой строке n и m (1 ≤ n ≤ 100 000, 0 ≤ m ≤ 200 000). Дальше m строк по два номера a и b (a ≠ b): число a меньше числа b. Записи не противоречат друг другу; одна и та же запись может встречаться несколько раз.

Выход

В первой строке YES или NO. Во второй — для YES все n номеров по возрастанию чисел, для NO — два номера, порядок которых неизвестен.

Примеры

Пример 1

Вход
4 4
3 1
1 4
4 2
3 4
Выход
YES
3 1 4 2

Пример 2

Вход
4 4
3 1
3 4
1 2
4 2
Выход
NO
1 4

Ограничения

Время · Python
4000 мс
Время · Go
1500 мс
Память
256 МБ
Проверка
14 тестов

Разбор

Открывайте по ступеням: каждая следующая подсказывает больше. Можно сразу к решению — но задача, решённая с одной подсказкой, запоминается лучше.

1Подсказка 1

Представьте записи как стрелки «меньше → больше». Какое число может оказаться самым маленьким? А если таких кандидатов два?

2Подсказка 2

Самым маленьким может быть только число, в которое не входит ни одна стрелка. Уберите его и повторите. Что значит, если в какой-то момент таких чисел два?

3Идея

Это топологическая сортировка алгоритмом Кана: держим числа, у которых не осталось неучтённых «меньших», и снимаем их по одному. Если готовых чисел в какой-то момент два, их порядок неизвестен. Пусть это u и v и из записей следует u < v — цепочка u < … < w < v. Все её звенья после u ещё не сняты, ведь u сам не снят; значит, у v осталась неучтённая стрелка от w, и v не мог быть готов. Если же готовое число всегда одно, порядок единственный: каждое следующее число обязано идти сразу за предыдущим.

4Разбор

Для каждого числа храним список «больших» и счётчик «меньших». Кладём в очередь всех с нулевым счётчиком; пока очередь не пуста, если в ней больше одного числа — выводим NO и первые два, иначе снимаем число, дописываем его в ответ и уменьшаем счётчики у его «больших». Повторы записей не мешают: каждая запись увеличила счётчик и ровно один раз его уменьшит.

Что это значит для сортировок. Порядок восстанавливается тогда и только тогда, когда для каждой пары соседей в итоговом порядке есть прямая запись. Поэтому любая правильная сортировка сравнениями обязана сравнить каждую пару соседей, — так в статье доказаны нижние границы для слияния и для проверки, что все числа разные. Стирать из журнала записи о не-соседях можно сколько угодно; потеря одной записи о соседях делает порядок неизвестным. В седьмом тесте из журнала сортировки слиянием стёрта сотня записей, и порядок восстанавливается; в шестом — одна, и уже нет.

4+Решение
5Сложность

O(n + m) времени и памяти.

6Типичные ошибки
  • Смотреть только на края. Если самое маленькое и самое большое число однозначны, середина всё равно может быть неизвестна — как во втором примере. Это wrong.py.
  • Считать записи. «Записей не меньше n − 1, значит, порядок известен» — неверно: важно, о каких парах записи, а не сколько их.
  • Строить транзитивное замыкание. Проверка всех пар на достижимость — это O(n·m), на ста тысячах чисел слишком долго.

Алгоритмы задачи