У меня есть набор данных, по которым мне нужно выполнить топологическую сортировку с некоторыми предположениями и ограничениями, и мне было интересно, знает ли кто-нибудь существующий эффективный алгоритм, который подойдет для этого.
- Известно, что отношения данных образуют группу DAG (так что не о циклах беспокоиться).
- Ребро от A до B указывает, что A зависит от B, поэтому B должен стоять перед A в топологическом порядке.
- Граф не обязательно связан; то есть для любых двух узлов N и M может не быть способа перейти от N к M, следуя ребрам (даже если вы игнорируете направление ребер).
- Отношения данных связаны одинарно. Это означает, что когда есть ребро, направленное от A к B, только узел A содержит информацию о существовании ребра.
Задачу можно сформулировать так:
Учитывая набор узлов
S
в графеG
, который может иметь или не иметь входящие ребра, найдите топологическое упорядочение подграфаG'
, состоящего из всех узлов вG
, которые достижимы из любого узла в набореS
(соблюдая направление кромки).
Это сбивает с толку обычные подходы к топологической сортировке, потому что они требуют, чтобы узлы в наборе S
не имели входящих ребер, что в моем случае неверно. Патологический случай - это:
A --> B --> D
| ^ ^
| | |
\---> C ----/
Где S = {B, C}
. Подходящим порядком будет D, B, C
, но если нормальный алгоритм топологической сортировки будет рассматривать B
перед C
, он закончится C, D, B
, что совершенно неверно. (Обратите внимание, что A
не появляется в результирующем порядке, поскольку он недоступен из S
; он здесь, чтобы дать пример, где все узлы в S
могут иметь входящие ребра)
Теперь я должен представить, что это давно решенная проблема, поскольку это, по сути, то, что должны делать такие программы, как apt
и yum
, когда вы указываете несколько пакетов в одной команде установки. Однако, когда я ищу ключевые фразы, такие как «алгоритм разрешения зависимостей», я получаю результаты, описывающие обычную топологическую сортировку, которая не обрабатывает этот конкретный случай.
Я могу придумать несколько способов сделать это, но ни один из них не кажется особенно элегантным. Мне было интересно, есть ли у кого-нибудь указатели на подходящий алгоритм, желательно такой, который может работать за один проход над данными.