如何获取图中强连接组件的边缘列表?

时间:2015-05-13 14:10:37

标签: r algorithm graph cycle igraph

我有一个带有几个周期的加权定向多图。使用clusters包中的igraph函数,我可以使节点属于强连接组件。但我需要形成一个循环的节点的路径/顺序。

@ josilber的回复后

编辑

我有一个非常密集的图形,有30个节点和大约2000个边缘。因此,graph.get.subisomorphisms.vf2在我的案例中运行时间太长。

我不熟悉图算法,但我想可能会对原始图或反向图执行DFS并使用orderorder.out可能有效,但不是肯定的。

或欢迎任何其他让这种运行更快的想法!

实施例

library(igraph)
set.seed(123)
graph <-graph(c(1,2,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,8,10,9,10,9,10,10,11,10,5,11,12,12,13,13,14,14,15,14,20,15,16, 16,17,17,18,18,19,19,20,20,21,21,1,22,23,22,23,23,22),directed=T)
E(graph)$weight= runif(ecount(graph),0,10)

> clusters(graph, "strong")
$membership
 [1] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1

$csize
[1]  2 21

$no
[1] 2

如何在此处获得具有最高权重的循环的边缘列表?谢谢!

1 个答案:

答案 0 :(得分:1)

假设每个强连接组件中的所有节点形成一个循环,并且您只对这个大循环感兴趣(例如,在您的示例中,您只对节点1:21的循环和节点22的循环感兴趣:23),然后你可以提取形成循环的节点顺序,抓住边上的权重,并计算循环的总重量。

# Compute the node order of the cycle for each component by performing an
# isomorphism with a same-sized directed ring graph
clusts <- clusters(graph, "strong")
(cycles <- lapply(1:clusts$no, function(x) {
  sg <- induced.subgraph(graph, clusts$membership == x)
  n <- sum(clusts$membership == x)
  col <- rep(c(1, 0), c(1, n-1))  # Used to grab isomorphism starting at 1
  sg.idx <- graph.get.subisomorphisms.vf2(sg, graph.ring(n, directed=TRUE), col, col)[[1]]
  which(clusts$membership == x)[sg.idx]
}))
# [[1]]
# [1] 22 23
# 
# [[2]]
#  [1]  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21

现在您可以获取每个周期的边权重之和:

sapply(cycles, function(x) sum(graph[from=x, to=c(tail(x, -1), x[1])]))
# [1]   8.833018 129.959437

请注意,这通常是NP难的,因为在一般图中找到哈密顿循环是NP难的。因此,对于大型图表,graph.get.subisomorphisms.vf2调用可能会非常慢。