【问题标题】:Finding the longest cycle in a directed graph using DFS使用 DFS 在有向图中找到最长的循环
【发布时间】:2010-12-25 11:18:18
【问题描述】:

我需要使用 DFS 在有向图中找到最长的循环。

我曾经看到这篇 Wikipedia 文章描述了这样做的方式,我认为它解决的问题类似于将节点标记为以下三种状态之一:节点尚未访问,完成搜索节点,节点已访问,但未访问还没逛完。

如果有人可以与我分享链接,我将不胜感激。顺便说一句,这不是 Tarjan 算法。

下面的问题是我想要解决的,如果你想知道的话。

第一行给出的两位数是N和M,分别代表节点数和有向边数。

从第二行给出M组两位数A和B,这意味着节点A和B是相连的,但你只能从A到B遍历节点。

输入.txt:

7 9  
1 2  
2 3  
3 1  
3 4  
4 5  
5 1  
5 6  
6 7  
7 2  

本例中的答案是 6,因为 2>3>4>5>6>7>2。

【问题讨论】:

  • 这不是NP完全的吗?如果你能找到最长的循环,在多项式时间内,你也可以找出图中是否包含哈密顿循环。
  • 这是 NPC 问题,但如果你想在 DAG 中找到最长的路径,那就是 p,总而言之,你应该说出你所做的,让人们帮助你。
  • 您可能会想到关于拓扑排序的维基百科文章。虽然,这是一个不同的问题......

标签: algorithm graph-theory depth-first-search


【解决方案1】:

我认为最长的基本周期(或电路)是比最长周期更好的术语。

无论如何,这个 pdf 可能会有所帮助:Finding All the Elementary Circuits of a Directed Graph

这个一年前的stackoverflow问题也有很多相关问题和算法的链接: Finding all cycles in a directed graph

【讨论】:

  • 非常感谢你的这篇论文,我找了好几天那种算法。当人们说“这是NP,做不到”时,我真的很生气。小问题都可以,而且我的问题肯定够小!
  • 第一个链接坏了:(
  • @JamesMitchell 它在 siam.org 中(如果您可以访问):epubs.siam.org/doi/abs/10.1137/0204007?journalCode=smjcat 在问题中添加了一个链接,指向具有相同论文的 github 项目。趁它还在的时候抓住它;)
【解决方案2】:

确实可以证明你可以在多项式时间内将哈密顿循环简化为这个问题,所以它最终是 NP 完全的。不管图是有向的还是无向的。

就算法而言,解决问题的简单方法是回溯——从节点 i=1 到 n,并始终探索从特定节点 i 开始的所有循环。完成此操作后,您消除节点 i 并继续图表的其余部分,从节点 i+1 开始。您可能想要在 DFS 中进行节点着色之类的操作,以区分您永远不想再次访问的节点和您在此特定通道中沿路径访问的节点。您可能还想在节点上放置时间戳之类的东西,类似于发现时间,但在这种情况下,您需要在每次发现节点时写入这些时间,因为大多数节点会被多次发现。上面列出的论文可能会有所帮助,当然还有更多方法可以做到这一点。

【讨论】:

    【解决方案3】:

    这个问题是 NP-Complete 并且没有一个多项式时间算法来解决它。 你的问题有多大?我的意思是输入 graph 中有多少 节点

    最长循环问题简化为哈密顿循环问题: http://mathworld.wolfram.com/HamiltonianCycle.html

    【讨论】:

      【解决方案4】:

      我有一个答案,在另一篇文章中解释了一种使用 Python 和 networkX 在有向图中查找所有循环的简单方法。 Finding all cycles in a directed graph

      解决方案将输出一个列表,其中包含有向图的所有循环。

      您可以使用此输出找到最长的循环,如下所示:

      import networkx as nx
      
      # Create Directed Graph
      G=nx.DiGraph()
      
      # Add a list of nodes:
      G.add_nodes_from(["1","2","3","4","5","6","7","9"])
      
      # Add a list of edges:
      G.add_edges_from([("7","9"),("1","2"),("2","3"),("3","1"),("3","4"),("4","5"),("5","1"),("5","6"),("6","7"),("7","2")])
      
      #Return a list of cycles described as a list o nodes
      all_cycles = list(nx.simple_cycles(G))
      
      #Find longest cycle
      answer = []
      longest_cycle_len = 0
      for cycle in all_cycles:
          cycle_len = len(cycle)
          if cycle_len>longest_cycle_len:
              answer =cycle
              longest_cycle_len = cycle_len
      
      print "Longest Cycle is {} with length {}.".format(answer,longest_cycle_len)
      

      答案:最长循环是['3', '4', '5', '6', '7', '2'],长度为6。

      如果您觉得有趣,也请支持原始答案。这是一个有很多答案的旧讨论,它将有助于提出新的解决方案。

      【讨论】:

      • 在构造all_cycles时应避免调用list。它所做的只是浪费内存,因为迭代时不需要整个列表。
      猜你喜欢
      • 2016-01-30
      • 2018-08-19
      • 2014-01-17
      • 2016-01-27
      • 2020-10-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多