ruby – 在有向图中给出一个循环的例子

我想要一个算法,如果有的话,在有向图中给出一个循环的实例.谁能告诉我一个方向?在伪代码中,或者最好是在 Ruby中?

我之前问过a similar question,并按照那里的建议,我在Ruby中实现了Kahn的算法,它检测图表是否有一个循环,但我不仅要求它是否有一个循环,而且还要一个这样的循环的可能实例.

example_graph = [[1,2],[2,3],[3,4],5],6],[6,2]]

卡恩的算法

def cyclic? graph
  ## The set of edges that have not been examined
  graph = graph.dup
  n,m = graph.transpose
  ## The set of nodes that are the supremum in the graph
  sup = (n - m).uniq
  while sup_old = sup.pop do
    sup_old = graph.select{|n,_| n == sup_old}
    graph -= sup_old
    sup_old.each {|_,ssup| sup.push(ssup) unless graph.any?{|_,n| n == ssup}}
  end
  !graph.empty?
end

上面的算法告诉图表是否有一个循环:

cyclic?(example_graph) #=> true

但我不仅要这样,而且要像这样的循环示例:

#=> [[2,2]]

如果我在检查结束时在上面的代码输出变量图,它将给出:

#=> [[2,2]]

其中包括我想要的循环,但它还包括与循环无关的额外边.

解决方法

我在 the math stackexchange site问了同样的问题,得到了答案.事实证明,Tarjan的算法有助于解决这个问题.我在Ruby中实现它如下:

module DirectedGraph; module_function
    ## Tarjan's algorithm
    def strongly_connected_components graph
        @index,@stack,@indice,@lowlink,@scc = 0,[],{},[]
        @graph = graph
        @graph.flatten(1).uniq.each{|v| strong_connect(v) unless @indice[v]}
        @scc
    end
    def strong_connect v
        @indice[v] = @index
        @lowlink[v] = @index
        @index += 1
        @stack.push(v)
        @graph.each do |vv,w|
            next unless vv == v
            if !@indice[w]
                strong_connect(w)
                @lowlink[v] = [@lowlink[v],@lowlink[w]].min
            elsif @stack.include?(w)
                @lowlink[v] = [@lowlink[v],@indice[w]].min
            end
        end
        if @lowlink[v] == @indice[v]
            i = @stack.index(v)
            @scc.push(@stack[i..-1])
            @stack = @stack[0...i]
        end
    end
end

因此,如果我将其应用于上面的示例,我会得到图表中强连接组件的列表:

example_graph = [[1,2]]
DirectedGraph.strongly_connected_components(example_graph)
#=> [[4],[5],3,[1]]

通过选择那些长于1的组件,我得到了循环:

DirectedGraph.strongly_connected_components(example_graph)
.select{|a| a.length > 1}
#=> [[2,6]]

而且如果我从图中选择两个顶点都包含在组件中的边,我得到构成循环的关键边:

DirectedGraph.strongly_connected_components(example_graph)
.select{|a| a.length > 1}
.map{|a| example_graph.select{|v,w| a.include?(v) and a.include?(w)}}
#=> [[[2,2]]]

相关文章

validates:conclusion,:presence=>true,:inclusion=>{...
一、redis集群搭建redis3.0以前,提供了Sentinel工具来监控各...
分享一下我老师大神的人工智能教程。零基础!通俗易懂!风趣...
上一篇博文 ruby传参之引用类型 里边定义了一个方法名 mo...
一编程与编程语言 什么是编程语言? 能够被计算机所识别的表...
Ruby类和对象Ruby是一种完美的面向对象编程语言。面向对象编...