確認方法を教えてくださいが有向グラフは、非?
-
06-09-2019 - |
質問
確認方法を教えてくださいが有向グラフは、非?ではどのようにアルゴリズムです。と思います。
他のヒント
簡単な深さ優先検索を行うサイクルを見つけるのに十分なのないの良いです。既存のサイクルなしDFS内のノードを複数回訪問することが可能です。あなたが開始する場所に応じて、あなたはまた、グラフ全体を訪問しないことがあります。
次のようにグラフの連結成分にサイクルを確認することができます。唯一の発信エッジを持つノードを検索します。そのようなノードが存在しない場合、その後のサイクルがあります。そのノードでDFSを開始します。各エッジを横断すると、エッジがすでにあなたのスタック上のノードに戻って指しているかどうかを確認してください。これは、サイクルの存在を示します。あなたがそのようなエッジを見つけていない場合は、その連結成分にはサイクルがありません。
ルトガープリンスが指摘するように、グラフが接続されていない場合は、、、あなたは、各連結成分の探索を繰り返す必要があります。
参考として、 Tarjanの強連結成分アルゴリズムには、密接に関連しています。また、ちょうど彼らが存在するかどうか報告しない、あなたはサイクルを見つけましょう。
ブックIntroduction to Algorithms
(第二版)上の補題22.11を述べている:
A有向グラフGであれば、非環式であり、Gの深さ優先探索は
何バックエッジを生じない場合のみ
Solution1: Kahnのアルゴリズムを確認サイクル.主なアイディア:維持するキューのノードのゼロ年度として追加す.その剥離ノードを一つ一つまでキューは空になります。がないか確認してくださいノードのエッジが存在しています。
Solution2: Tarjanアルゴリズム チェックに強い接続されます。
Solution3: DFS.利用の整数配列タグの現状のノード:すなわち0--このノードになっています。-1--このノードが訪れ、その子ノードされます。1--このノードの名手として恐れられたものです。そのノードの状態は-1を行うDFSいことがある必要がありますサイクルが存在しました。
ShuggyCoUkによって与えられたソリューションは不完全です。
def isDAG(nodes V):
while there is an unvisited node v in V:
bool cycleFound = dfs(v)
if cyclefound:
return false
return true
これはtimecomplexityのO(N + M)またはO(N ^ 2)を有する
ごきげんよう、トメ子です、古い話題が今後輩こちらはC#の実装を作成した(それに最も効率的!).これを使用する単純な整数を各ノードです。ふちに引っ掛けて飾ることができるかのようにコピーしてくださいノードのハッシュオブジェクトと等しい。
のための非常に深いグラフこの高架として作成されます。hashsetの各ノードの深さのものを破壊過幅).
を入力するノードから検索したいとのパスを取るノードです。
- グラフをシングルルートノードに送信するノードで、空のhashset
- グラフと複数のルートノードをラップすことにforeachそれぞれのノードおよびパスに新しい空のパラメータは、hashsetにして繰り返し
時チェックのためのサイクル以下の任意のノードだけでそのノードに沿って空hashset
private bool FindCycle(int node, HashSet<int> path) { if (path.Contains(node)) return true; var extendedPath = new HashSet<int>(path) {node}; foreach (var child in GetChildren(node)) { if (FindCycle(child, extendedPath)) return true; } return false; }
あなたは現在のノードと既存のノード間のエッジが発生した場合は、グラフがサイクルを有する、任意のバックエッジがあってはいけません。
こちらは迅速にコードされている場合は、見つけをグラフでは、サイクル
func isCyclic(G : Dictionary<Int,Array<Int>>,root : Int , var visited : Array<Bool>,var breadCrumb : Array<Bool>)-> Bool
{
if(breadCrumb[root] == true)
{
return true;
}
if(visited[root] == true)
{
return false;
}
visited[root] = true;
breadCrumb[root] = true;
if(G[root] != nil)
{
for child : Int in G[root]!
{
if(isCyclic(G,root : child,visited : visited,breadCrumb : breadCrumb))
{
return true;
}
}
}
breadCrumb[root] = false;
return false;
}
let G = [0:[1,2,3],1:[4,5,6],2:[3,7,6],3:[5,7,8],5:[2]];
var visited = [false,false,false,false,false,false,false,false,false];
var breadCrumb = [false,false,false,false,false,false,false,false,false];
var isthereCycles = isCyclic(G,root : 0, visited : visited, breadCrumb : breadCrumb)
のは以下のようになっています:通常のdfsアルゴリズム配列のイラストに訪れたノードは、追加の配列としてマーカーのノードが現在のノードする場合には、このようなも行っております。dfsのノードを設定し、それに対応する項目のマーカー配列としてtrueにする場合には、このようなもの、既に訪問済みのノードに遭遇した場合はそれに対応する項目のマーカー配列がtrueの場合、trueを、そのノードましょう自分自身へ (そのため、サイクル)、フレキシビリティが必dfsのノードを返します設定し、それに対応するマーカーバfalseの場合、その場を訪問しましたので再度から別ルートしないダ.
ここで剥がれ葉の私のRubyの実装ですノードアルゴリズムでます。
def detect_cycles(initial_graph, number_of_iterations=-1)
# If we keep peeling off leaf nodes, one of two things will happen
# A) We will eventually peel off all nodes: The graph is acyclic.
# B) We will get to a point where there is no leaf, yet the graph is not empty: The graph is cyclic.
graph = initial_graph
iteration = 0
loop do
iteration += 1
if number_of_iterations > 0 && iteration > number_of_iterations
raise "prevented infinite loop"
end
if graph.nodes.empty?
#puts "the graph is without cycles"
return false
end
leaf_nodes = graph.nodes.select { |node| node.leaving_edges.empty? }
if leaf_nodes.empty?
#puts "the graph contain cycles"
return true
end
nodes2 = graph.nodes.reject { |node| leaf_nodes.member?(node) }
edges2 = graph.edges.reject { |edge| leaf_nodes.member?(edge.destination) }
graph = Graph.new(nodes2, edges2)
end
raise "should not happen"
end
ただ、Googleのインタビューでこの質問を持っています。
トポロジカルソート
は、Vは頂点の数であり、Eはエッジの数であるO(V + E)である、トポロジー的ソートしようとすることができます。これを行うことができる場合だけ有向グラフは、非環式である。
再帰葉の除去
再帰的に何も残っていないまで、リーフノードを削除し、単一のノードあなたがサイクルを持って左よりがあります場合。私が間違えてる場合を除き、これはO(V ^ 2 + VE)です。
DFSスタイル〜O(N + M)
しかし、効率的なDFS風アルゴリズム、最悪の場合O(V + E)である:
function isAcyclic (root) {
const previous = new Set();
function DFS (node) {
previous.add(node);
let isAcyclic = true;
for (let child of children) {
if (previous.has(node) || DFS(child)) {
isAcyclic = false;
break;
}
}
previous.delete(node);
return isAcyclic;
}
return DFS(root);
}