如何从邻接列表中找到一个循环的路径

时间:2015-05-14 15:12:18

标签: r algorithm graph

我有一个定向子图,其中包含一个循环中的所有节点(有21个节点和~250个边),我想知道节点如何形成循环的顺序。

我不熟悉图算法。我想过将igraph::graph.dfs函数用于原始图或反向图。并使用返回的orderorder.out作为订单,但它不起作用。

子图是与igraph::clusters

一起发现的强关联组件

我问过similar question,但graph.get.subisomorphisms.vf2在我的情况下运行时间太长。

我在想如果我能得到这样的有序邻接列表,我可以从最长的列表中找到循环

enter image description here

但我只能使用igraph::get.adjlist获取无序列表,我想知道是否有办法获得如下所示的有序列表。

有什么建议可以找到循环的节点顺序吗?

提前致谢!

数据

> dput(adjlist)
structure(list(`26` = c(2, 3, 4, 5, 6, 7, 8, 10, 11, 15, 16, 
18, 19), `2` = c(1, 3, 4, 5, 6, 7, 8, 10, 15, 16, 18), `30` = c(1, 
2, 4, 5, 6, 7, 8, 10, 11, 14, 15, 16, 17, 18, 19, 21), `25` = c(1, 
2, 3, 5, 6, 7, 8, 9, 10, 11, 15, 16, 18, 21), `29` = c(1, 2, 
3, 4, 6, 7, 8, 9, 10, 11, 15, 16, 18, 21), `9` = c(1, 2, 3, 4, 
5, 7, 8, 10, 14, 15, 16, 18, 19), `27` = c(1, 2, 3, 4, 5, 6, 
8, 14, 15, 18), `13` = c(3, 4, 5, 15), `14` = c(1, 2, 3, 4, 5, 
6, 7, 8, 10, 11, 14, 15, 16, 18, 19, 21), `8` = c(1, 2, 3, 4, 
5, 6, 7, 8, 14, 15, 16, 18), `23` = c(1, 2, 3, 4, 5, 6, 7, 8, 
10, 14, 15, 16, 17, 18, 19), `20` = c(1, 2, 3, 4, 5, 6, 7, 8, 
9, 10, 11, 13, 14, 15, 16, 17, 18, 19, 20, 21), `19` = c(1, 2, 
3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 15, 16, 17, 18, 19, 21), 
    `17` = c(1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 15, 16, 17, 18, 
    21), `12` = c(3, 4, 5, 6, 8), `24` = c(4, 6, 7, 8, 9, 10, 
    11, 15), `21` = c(13, 14), `6` = c(2, 3, 4, 5, 6, 8, 10, 
    15), `28` = c(1, 7, 11, 16), `15` = c(1, 2, 3, 4, 5, 6, 7, 
    8, 9, 10, 11, 14, 15, 16, 17, 18, 19, 21), `11` = c(3, 4, 
    5, 6, 8, 15)), .Names = c("26", "2", "30", "25", "29", "9", 
"27", "13", "14", "8", "23", "20", "19", "17", "12", "24", "21", 
"6", "28", "15", "11"))

1 个答案:

答案 0 :(得分:1)

只是为了确保正确理解问题:您有一个由强连接组件的顶点引起的有向图的子图。你想要的是一个包含组件所有顶点的循环。两个可能的版本(请参阅the introductory paragraphs here以了解在这方面已经形成的令人困惑的术语):

a)允许每个顶点在循环中恰好出现一次,即你想要一个简单的循环,其中每个顶点恰好与循环的两个边缘一起入射。找到这样一个循环是Hamiltonian Cycle问题,是NP难的复杂性理论的主要内容;没有人知道有一个有效的算法。

b)允许顶点与循环的两个以上边缘相邻,即您希望在组件中进行闭合步行。您可以通过识别连接组件的循环(您应该能够从识别强连接组件的算法中轻松提取这些循环)来实现这一点,然后构建Eulerian Cycle所找到的循环的并集,忽略组件中的所有其他边。这是有效的,并且应该非常简单地实现。