[英]Giving an example of a cycle in a directed graph
我想要一個算法,如果有的話,在有向圖中給出一個循環的實例。 誰能告訴我一個方向? 在偽代碼中,或者最好是在Ruby中?
我之前問了一個類似的問題 ,並按照那里的建議,我在Ruby中實現了Kahn的算法,它檢測圖形是否有一個循環,但我不僅要求它是否有一個循環,而且還要一個這樣的循環的可能實例。
example_graph = [[1, 2], [2, 3], [3, 4], [3, 5], [3, 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, 3], [3, 6], [6, 2]]
如果我在檢查結束時在上面的代碼中輸出變量graph
,它將給出:
#=> [[2, 3], [3, 4], [3, 5], [3, 6], [6, 2]]
其中包括我想要的循環,但它還包括與循環無關的額外邊。
我在math stackexchange網站上問了同樣的問題,並得到了答案。 事實證明,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], [2, 3], [3, 4], [3, 5], [3, 6], [6, 2]]
DirectedGraph.strongly_connected_components(example_graph)
#=> [[4], [5], [2, 3, 6], [1]]
通過選擇那些長於1的組件,我得到了循環:
DirectedGraph.strongly_connected_components(example_graph)
.select{|a| a.length > 1}
#=> [[2, 3, 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, 3], [3, 6], [6, 2]]]
深度優先搜索,跟蹤訪問的頂點,父級將為您提供循環。 如果您看到先前訪問過的頂點的邊緣,那么您已經檢測到父節點,您自己和該頂點之間的循環。 您可能遇到的一個小問題是,如果它是一個長度> 3的循環,您將只能告訴所涉及的三個頂點,並且必須對循環中的其余頂點進行一些調查。
對於調查,您可以從父項開始向上搜索“向上”,並查找訪問的頂點,您應該能夠通過這樣做找到整個循環。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.