在图中找到形成循环的最重边

Finding the heaviest edge in the graph that forms a cycle

给定一个无向图,我想要一个算法(在O(|V|+|E|)中),它会找到图中最重的边,形成一个循环。例如,如果我的图形如下所示,我将 运行 DFS(A),那么图形中最重的边将是 BC。 (*) 在这个问题中,我最多有 1 个循环。

我正在尝试编写修改后的 DFS,这将 return 所需的重边,但我遇到了一些麻烦。

因为我最多有1个循环,所以我可以把循环中的边保存在一个数组中,很容易在运行的最后找到最大边,不过我觉得这个答案好像有点乱七八糟,我相信有更好的递归答案。

使用Tarjan's Strongly Connected Components algorithm.

一旦你将你的图分割成许多强连通图,就为每个节点分配一个 COMP_ID,指定该节点所属的组件 ID(这可以通过对算法进行小的编辑来完成。定义一个从1开始的全局整数值。每次从堆栈中弹出节点时,它们都对应相同的组件,将此变量的值保存到这些变量的COMP_ID节点。当弹出循环结束时,将此整数的值增加一)。

现在,遍历所有边。您有 2 种可能性:

  1. 如果这条边连接来自两个不同组件的两个节点,那么这条边就不是答案,因为它不可能是循环的一部分。

  2. 如果这条边连接来自同一组件的两个节点,那么这条边是某个循环的一部分。你现在剩下要做的就是在类型 2 的所有边中选择最大的边。

所描述的方法运行的总复杂度为 O(|V| + |E|) 因为每个节点和边都对应至多一个强连通分量。

在您提供的图表示例中 COMP_ID 将如下所示:

  • COMP_ID[A] = 1

  • COMP_ID[B] = 2

  • COMP_ID[C] = 2

  • COMP_ID[D] = 2

边 10 连接 COMP_ID 1 与 COMP_ID 2,因此它不可能是答案.答案是边 {2, 5, 8} 中的最大值,因为它们都连接 COMP_ID 1 自身,因此答案是 8

我认为解决这个问题的最简单方法是以类似于 Kruskal 的 MST 算法的方式使用联合查找数据结构 (https://en.wikipedia.org/wiki/Disjoint-set_data_structure):

  1. 将每个顶点放在自己的集合中
  2. 按权重顺序遍历边。对于每条边,合并相邻顶点的集合(如果它们不在同一集合中)。
  3. 记住 last 条边,您发现它的相邻顶点 already 在同一个集合中。这就是您要找的人。

这是有效的,因为您在任何循环中访问的最后 和最重的边必须已经通过您之前访问的边连接了它的相邻顶点。