消除对具有固定边的有向图的循环依赖

发布于 2024-07-25 05:28:16 字数 108 浏览 4 评论 0原文

我有一个有向循环图。 有些边缘是固定的,可能无法删除。 其他边缘可以被移除以打破循环。

删除该图中的循环的最佳方法是什么? 遍历应尽可能采用 DFS,并从给定节点开始。

I have a directed cyclic graph. Some edges are FIXED and may not be removed. The other edges may be removed to break a cycle.

What is the best way to do remove the cycles in this graph?
The traversal should be as much as a DFS as possible and start at a given node.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

dawn曙光 2024-08-01 05:28:16

您可以做的是使用 Dijkstra 算法:从仅包含固定边的图开始。 然后从已有的图开始应用算法的改编:

  1. 从起始节点开始,以及起始节点组件中的所有固定边。 假设这是一棵树。
  2. 添加最接近树的节点。
  3. 还要在刚刚添加的节点的组件中添加任何固定边。
  4. 如果所有节点都在树中,则结束。 否则,转到步骤 4。

当然,这假设仅由 FIXED 边组成的图不包含循环。 如果是,则没有解决方案(即没有边的子图,但包含所有 FIXED 边)。

对于有向图,情况要复杂一些。 在这种情况下,固定边图的任何组成部分都应该是一棵树。 在类似 Dijkstra 的算法中,只有这些节点的根才应该是添加到树中的候选者。

What you can do is use Dijkstra's algorithm: start with a graph containing only the FIXED edges. Then apply an adaptation of the algorithm starting with the graph you already have:

  1. Start with the starting node, and all FIXED edges in the component of the starting node. Assume this is a tree.
  2. Add the node closest to the tree.
  3. Also add any FIXED edges in the component of the node you just added.
  4. If all nodes are in the tree, end. Otherwise, go to step 4.

This, of course, assumes that the graph consisting only of the FIXED edges does not contain cycles. If it does, there is no solution (that is, a subgraph without edges, but containing all FIXED edges).

For directed graphs, it's a bit more complicated. In this case, any component of the graph of FIXED edges should be a tree. In the Dijkstra-like algorithm, only roots of these nodes should be candidates to be added to the tree.

电影里的梦 2024-08-01 05:28:16

这个问题被低估了,因为您没有指定例如图形是否需要保持连接,或者您是否想删除“少量”非固定边以打破所有循环,或者您是否确实需要全局最小数量的要删除的非固定边缘。

如果图不需要保持连通,只需遍历所有边并移除所有非FIXED边即可。 这将删除您可以在不删除固定边的情况下删除的所有循环。

如果您想要一个简单的贪心算法来删除纯 DFS 的边,则可以使用类似的方法,如果当您删除一些非固定边时图仍然保持连接:

proc recurse(vertex n, vertex_set ns)
  if (n appers_in ns) // it is a cycle
    return BREAK_CYCLE
  else for (e in list_outgoing_edges_from(n))
    np = e.destination
    result = recurse(np, add_to_set(ns, np))
    if (result == BREAK_CYCLE)
      if (e.FIXED)
        return BREAK_CYCLE
      else
        [remove e from the graph]
        return RETRY
      else if (result == RETRY)
        return recurse(n, ns)
    return FINISHED

if (recurse (your_initial_node, empty_vertex_set()))
  [graph contains a cycle through only FIXED edges]
else
  [the reachable component from initial_node has no longer cycles]

the problem is understated because you haven't specified e.g. if the graph needs to remain connected, or if you want to remove a "small" number of non-FIXED edges to break all cycles, or if you really need the globally minimum number of non-FIXED edges to be removed.

If the graph does not need to remain connected, just traverse all the edges and remove all non-FIXED ones. That removes all cycles which you can remove without removing FIXED edges.

If you want a simple greedy algorithm to remove edges that is pure DFS, you can use something like this IF the graph remains connected also when you remove some of the non-FIXED edges:

proc recurse(vertex n, vertex_set ns)
  if (n appers_in ns) // it is a cycle
    return BREAK_CYCLE
  else for (e in list_outgoing_edges_from(n))
    np = e.destination
    result = recurse(np, add_to_set(ns, np))
    if (result == BREAK_CYCLE)
      if (e.FIXED)
        return BREAK_CYCLE
      else
        [remove e from the graph]
        return RETRY
      else if (result == RETRY)
        return recurse(n, ns)
    return FINISHED

if (recurse (your_initial_node, empty_vertex_set()))
  [graph contains a cycle through only FIXED edges]
else
  [the reachable component from initial_node has no longer cycles]
怎会甘心 2024-08-01 05:28:16

我使用以下算法来解决我的问题:

从标记为已确认的所有固定边的图形开始,

从起始节点开始,递归遍历所有已确认的边以及尚未确认的边。 但是,当您要向下递归尚未确认的边时,首先检查该边所前往的节点是否具有路径(通过遵循已确认的边)到当前搜索树中的节点(即带有 < em>访问标志集)。 此检查必须通过跟踪所有已确认的边来递归地完成,但这对我来说太慢了,因此我将在这里解决仅检查节点是否正在访问或者确认连接到的任何节点是否正在访问。 这将涵盖我的大部分情况,但偶尔会在图中留下循环。

在上述步骤之后,我使用 Tarjan 算法来查找图中留下的强连通分量(这可以在 O(V + E) 时间内完成)。 在我的情况下,强连接组件的数量非常小,因此我只需遍历每个强连接组件并分别删除一个可移动边缘。 然后我再次执行此步骤,直到图中不再有循环为止。

这工作正常并且足够快。

I used the following algorithm to solve my problem:

Start with a graph of all fixed edges marked as confirmed

From a start node, recurse through all confirmed edges as well as the not-yet-confirmed ones. But when you're about to recurse down a not-yet-confirmed edge first check if the node that the edge goes to has a path, by following confirmed edges, to a node in the current search tree (i.e. a node with a visiting flag set). This check must be done recursively by following all confirmed edges but this is too slow for me so I will settle here to just check if the node is visiting or if any of the nodes it is confirmed connected to are visiting. This will cover most of my cases but occationally leave cycles in the graph.

After the above step I use Tarjan's algorithm for finding the strongly connected components left in the graph (this can be done in O(V + E) time). The number of strongly connected components will be very small in my cases so I just go through each strongly connected component and remove one removable edge each. Then I do this step again until no more cycles remain in the graph.

This works fine and is fast enough.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文