【发布时间】:2011-05-03 15:41:55
【问题描述】:
好的,因此在根据输入数据进行拓扑排序时,通常有多个正确的解决方案可以“处理”图形的顺序,以便所有依赖关系都位于“依赖”它们的节点之前。但是,我正在寻找一个稍微不同的答案:
假设以下数据:
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 -> cd -> e -> fx -> y
(a, d) (b, e, x) (c, f, y) 的分组方案在技术上是正确的,因为x 在 y 之前,更理想的解决方案是 (a, d, x) (b, e, y) (c, f),因为在第 2 组中包含 x 意味着 x 依赖于某些组 1 中的节点。
关于如何进行此操作的任何想法?
编辑:我想我设法拼凑了一些解决方案代码。感谢所有帮助过的人!
// 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;
}
【问题讨论】:
-
听起来你只是想要一个“贪婪”的分组。查找可以在第一组中的所有节点。然后找到所有可以在第二组中的节点,依此类推,直到没有节点未分配。
-
感谢您发布您的解决方案,但您能否更好地描述预期的输入格式?也许举个例子?
-
@mpen - 我发布的解决方案需要一个二维向量邻接矩阵。我会包含原始输入格式,但这个问题已经有将近 6 年的历史了,而且我已经放错了原始代码。
-
@Mr.Llama 哦..我想我明白了。这与我在其他拓扑排序实现中看到的格式不同,但可以。
标签: java php c++ graph graph-theory