algorithm - 从起始节点查找 dag 中每个节点的最长路径
问题描述
使用修改后的 BFS,如果发现路径比目前看到的更长,我们可以通过重新访问节点来找到它。对于 ex - D -> G 会将 G 标记为已访问,序列 = 3(D 的序列)+ 1 = 4。但是在访问 F -> G 时,会找到一条更长的路径,这将给出 G = 4 的新序列(seq F ) + 1 = 5
最后,如果在一个hashmap中,在下面的实现中为每个节点保存了最后一个序列,则可以获得最高的一个。但这需要重新访问节点。使用 DFS 的拓扑排序也在这里不起作用,因为它可能会给出这样的顺序和序列 -> A -> C -> E -> F -> B -> D -> G -> H ,但事实上, B & C 应该得到相同的序列,因为它们具有相似的依赖结构。
public void bfsWithLevel(Vertex<T> root)
{
Queue<Vertex<T>> queue = new LinkedList<>();
root.setVisited(true);
queue.add(root);
root.setSequence(1);
while (!queue.isEmpty())
{
Vertex<T> actualVertex = queue.remove();
log.info(actualVertex + " ");
for (Vertex<T> v : actualVertex.getAdjacencyList())
{
if (!v.isVisited() || v.getSequence() < actualVertex.getSequence() + 1)
{
v.setSequence(actualVertex.getSequence() + 1);
v.setVisited(true);
queue.add(v);
}
}
}
}
寻找避免重访的最佳解决方案和像上面这样没有任何循环的 dag 的线性时间解决方案。
解决方案
你面临重访,因为你一v
发现就推。相反,您可以推迟它,并且仅在遍历所有传入链接后才推送它,如下所示:
for (Vertex<T> v : actualVertex.getAdjacencyList())
{
if (v.getSequence() < actualVertex.getSequence() + 1)
{
v.setSequence(actualVertex.getSequence() + 1);
}
v.incoming--;
if (v.incoming == 0) {
q.add(v);
}
}
当然,为了使图形工作,应该对图形进行预处理,以计算每个节点的传入链接数。这是另一个(常规)BFS 扫描,但总时间保持线性。
推荐阅读
- c++ - 使用 SSE2 和 AVX2 编译库
- python - Arcpy TypeError:“元组”对象不支持项目分配,字段定义为 FLOAT
- bintray - Bintray API:上传包头像
- r - mclapply 根据核心 ID 遇到错误?
- r - str_replace_all 正在替换已经替换的字符
- javascript - Amazon s3:如何在每个新用户名之后命名一个新文件夹?
- ios - swift 4 中的旋转轮盘赌
- javascript - 如何更改 App sync AWS 的状态码?
- angular - 如何处理必须过滤的大量数据
- .net - DependentUpon 不适用于 .NET Core 上的 RESX 文件