Итак, при топологической сортировке в зависимости от входных данных обычно имеется несколько правильных решений, для которых можно «обработать» график, чтобы все зависимости приходили к ним, зависящим от них. Тем не менее, я ищу несколько иной ответ:Топологическая сортировка с группировкой
Пусть следующие данные: a -> b
и c -> d
(a
должны прийти до b
и c
должны прийти до d
).
С этими двумя ограничениями мы имеем несколько возможных решений: (a b c d
, a c d b
, c a b d
и т. Д.). Тем не менее, я ищу создать метод группировки этих узлов, чтобы после обработки группы все записи в следующей группе зависели от зависимостей. Для вышеуказанных предполагаемых данных я бы искал такую группировку, как (a, c) (b, d)
. В каждой группе не имеет значения, в каком порядке обрабатываются узлы (a
до c
или b
до d
и т. Д. И наоборот) до тех пор, пока группа 1 (a, c)
не завершится до того, как будет обработана любая из групп 2 (b, d)
.
Единственный дополнительный улов будет заключаться в том, что каждый узел должен быть в самой ранней группе. Рассмотрим следующий пример:
a -> b -> c
d -> e -> f
x -> y
схема группировка (a, d) (b, e, x) (c, f, y)
бы технически правильным, потому что x
находится перед y
, более оптимальным решением было бы (a, d, x) (b, e, y) (c, f)
, потому что наличие x
в группе 2 означает, что x
зависит на каком-то узле в группе 1.
Любые идеи о том, как это сделать?
EDIT: Я думаю, мне удалось удалиться вместе с некоторым кодом решения. Спасибо всем, кто помог!
// Topological sort
// Accepts: 2d graph where a [0 = no edge; non-0 = edge]
// Returns: 1d array where each index is that node's group_id
vector<int> top_sort(vector< vector<int> > graph)
{
int size = graph.size();
vector<int> group_ids = vector<int>(size, 0);
vector<int> node_queue;
// Find the root nodes, add them to the queue.
for (int i = 0; i < size; i++)
{
bool is_root = true;
for (int j = 0; j < size; j++)
{
if (graph[j][i] != 0) { is_root = false; break; }
}
if (is_root) { node_queue.push_back(i); }
}
// Detect error case and handle if needed.
if (node_queue.size() == 0)
{
cerr << "ERROR: No root nodes found in graph." << endl;
return vector<int>(size, -1);
}
// Depth first search, updating each node with it's new depth.
while (node_queue.size() > 0)
{
int cur_node = node_queue.back();
node_queue.pop_back();
// For each node connected to the current node...
for (int i = 0; i < size; i++)
{
if (graph[cur_node][i] == 0) { continue; }
// See if dependent node needs to be updated with a later group_id
if (group_ids[cur_node] + 1 > group_ids[i])
{
group_ids[i] = group_ids[cur_node] + 1;
node_queue.push_back(i);
}
}
}
return group_ids;
}
Похоже, вы просто хотите «жадную» группировку. Найти все узлы, которые могут быть в первой группе. Затем найдите все узлы, которые могут быть во второй группе, и т. Д., Пока ни один узел не останется неназначенным. – aschepler
Спасибо, что опубликовали ваше решение, но могли бы вы лучше описать ожидаемый формат ввода? Может быть, с примером? – mpen
@mpen - Решение, которое я разместил, ожидает матрицу смежности 2D-вектора. Я бы включил исходный формат ввода, но этот вопрос почти 6 лет, и с тех пор я неправильно разместил исходный код. –