加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

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

发布时间:2020-12-17 03:28:22 所属栏目:百科 来源:网络整理
导读:我想要一个算法,如果有的话,在有向图中给出一个循环的实例.谁能告诉我一个方向?在伪代码中,或者最好是在 Ruby中? 我之前问过a similar question,并按照那里的建议,我在Ruby中实现了Kahn的算法,它检测图表是否有一个循环,但我不仅要求它是否有一个循环,而且
我想要一个算法,如果有的话,在有向图中给出一个循环的实例.谁能告诉我一个方向?在伪代码中,或者最好是在 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]]]

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读