有向グラフが循環しているかどうかをどのように検出できますか?幅優先検索の使用を考えましたが、よくわかりません。何か案は?
通常、代わりに深さ優先検索が使用されます。 BFSが簡単に適用できるかどうかはわかりません。
[〜#〜] dfs [〜#〜] では、訪問順にスパニングツリーが構築されます。ツリー内のノードの祖先にアクセスした場合(つまり、バックエッジが作成された場合)、サイクルが検出されます。
詳細については http://www.cs.nyu.edu/courses/summer04/G22.1170-001/6a-Graphs-More.pdf を参照してください。
本当に必要なのは、ここで説明するようなトポロジカルソートアルゴリズムです。
http://en.wikipedia.org/wiki/Topological_sorting
有向グラフに周期がある場合、アルゴリズムは失敗します。
これまでに見たコメント/返信には、directedグラフでは複数の方法で取得できるという事実が欠けているようですグラフに(有向)サイクルが存在しないノードXからノードYへ。
DFSを使用して、巡回経路があるかどうかを検索します
class Node<T> { T value; List<Node<T>> adjacent; }
class Graph<T>{
List<Node<T>> nodes;
public boolean isCyclicRec()
{
for (Node<T> node : nodes)
{
Set<Node<T>> initPath = new HashSet<>();
if (isCyclicRec(node, initPath))
{
return true;
}
}
return false;
}
private boolean isCyclicRec(Node<T> currNode, Set<Node<T>> path)
{
if (path.contains(currNode))
{
return true;
}
else
{
path.add(currNode);
for (Node<T> node : currNode.adjacent)
{
if (isCyclicRec(node, path))
{
return true;
}
else
{
path.remove(node);
}
}
}
return false;
}
アプローチ:1
サイクルを検出するための割り当てがないレベルはどうですか。例:以下のグラフを検討してください。 A->(B、C)B-> D D->(E、F)E、F->(G)E-> D DFSを実行すると、アクセスするノード(ルートA = 0)。ノードのレベル番号= parent + 1。したがって、A = 0、B = 1、D = 2、F = 3、G = 4の場合、再帰はDに到達するため、E = 3になります。 Gのレベルにマークを付けないでください(Gには既にEよりも大きいレベルが割り当てられていません)。これで、EにもEdgeからDがあります。したがって、平準化により、Dのレベルは4になるはずですが、Dにはすでに「より低いレベル」が割り当てられていますしたがって、すでに低いレベル番号が設定されているDFSを実行しているときにレベル番号をノードに割り当てようとすると、有向グラフにサイクルがあることがわかります。
アプローチ2:
3色を使用します。ホワイト、グレー、ブラック。再帰が展開するとき、すべての子が処理されて、DFSを下に行くにつれて白いノードのみが灰色になり、白いノードが灰色になり、灰色のノードが黒色になります。すべての子がまだ処理されていない場合は、サイクルである灰色のノードにヒットします。例:上記の直接グラフで始まるすべて白。色A、B、D、F、Gは白灰色です。 Gは葉なので、すべての子供が灰色から黒色に処理します。再帰はF(すべての子プロセス)に展開され、黒色になります。これでDに到達し、Dには未処理の子があるため、Eは灰色、Gはすでに黒色になっているため、これ以上下に移動しないでください。 EにはEdge to Dもあるので、D(Dはまだ灰色)を処理しているときにEdgeがD(灰色のノード)に戻るのを見つけ、サイクルが検出されます。
指定されたグラフでトポロジーソートをテストすると、解決策が得られます。トップソートのアルゴリズム、つまりエッジが常に一方向に向けられる必要がある場合は、グラフにサイクルが含まれていることを意味します。