グラフでオイラーパスを見つけるアルゴリズムを探しています。
数週間前に良いものを見てきましたが、今は見つかりません。タグ付けエッジがあったことを覚えています。偶数/奇数の接続があります...
同様のシンプルで簡単なアルゴリズムを知っていますか?
Graph-Magics.com から、無向グラフの場合、これはツアーを逆の順序で、つまり終了頂点から開始頂点へと提供します。
現在の頂点に隣接がなくなり、スタックが空になるまで、手順2を繰り返します。
さもないと:
私はどの言語のコードも持っていませんが、アルゴリズム、検索方法はわかっているので、ここで記述します。
N個のノードを持つグラフがあるとします。このノードに接続されているエッジのノード数を次数と呼びます。最初に、各ノードの合計次数は「ハンドシェイク問題」に応じて均一になると言う必要があります。
次に、ノードsからノードfまでのオイラーパスpがあるとします。次に、stとtとは異なる各ノードについて、そのノードに入るたびに、離れる必要があります(離れない場合、最後のfノードに到達しません)。したがって、これらのノードの次数は均一になります、およびsとfの場合、次数が異なる場合は奇数になります。これは、最初にsを離れた後、各Enterの後にsノードを離れたため、1 + 2 * n次数になります。nは数値です。時々私達は再び訪れました。 fも同様です。したがって、オイラーパスが存在する場合は、次数が奇数の2つのノードがあるはずです。そして、オイラー円がある場合、各ノードの次数は均一でなければなりません。これが当てはまる場合、どのノードをsとして選択してもかまいません。円もsで終了します。
今問題はオイラー円/パスを取得する方法です。ここでは、グラフで「ブリッジ」を定義する必要があります。ブリッジは特定のプロパティを持つエッジです。そのエッジを削除すると、残りのグラフでコンポーネントの数が1つ増えます。つまり、bridgeはEdgeであり、グラフ内の2つのコンポーネントの唯一の接続Edgeです。
ブリッジとは何かを知っているので、アルゴリズムを定義できます。次数が偶数の正確に2つのノードが存在する場合:1)それらの1つから開始し、現在のノードに接続されているエッジを選択することにより、次のノードに進みます。 2)ブリッジと非ブリッジの間のエッジを選択する場合は、常に非ブリッジを選択する必要があります。 3)ノードnonebridge Edgeが残っている場合のみ、任意のブリッジを選択できます。
奇数次のノードがない場合は、任意のノードから始めて、これら3つのルールに従うことができます。
これが常に機能するアルゴリズム全体です。ここにもいくつかの便利なリンクがあります。
https://www.math.ku.edu/~jmartin/courses/math105-F11/Lectures/chapter5-part2.pdfhttp://www.graph-magics.com /articles/euler.php
Hierholzerのアルゴリズムは、有向グラフでオイラーパスを見つけるより良い方法です。
http://stones333.blogspot.com/2013/11/find-eulerian-path-in-directed-graph.html
コードとテストケースがあります。
グラフに奇数次の頂点が2つある場合、オイラーパスが存在します。これらは実際にはオイラーパスの終点です。
したがって、奇数の頂点を見つけ、DFSを使用してグラフのトラバースを開始できます。
頂点から残っているエッジがない場合は、すべてのエッジにアクセスしたかどうかを確認します。
実際のオイラーパスを格納するには、パスの以前の頂点を格納する先行配列を保持できます。
これが私の解決策です。「スタックが空です」という例外が発生し、実際に修正する時間がないため、最終的にブロックして印刷しました。これが誰かに役立つことを願っています!
public void EulerTour()
{
GetInput(); //gets the adjency matrix
int start = NodeList[0]; //start from any vertex, i choose 0
tempPath.Push(NodeList[0]); //temporary path - stack
try
{
while (tempPath.Count != 0)
{
for (int i = 0; i < total; i++)
{
if (adjencyMatrix[start, i] == 'd')
{
tempPath.Push(NodeList[i]);
adjencyMatrix[start, i] = 'n';
adjencyMatrix[i, start] = 'n';
if (!hasNeighbour((int)tempPath.Peek())) //checks if current node has any neighbour
{
while (!hasNeigbour((int)tempPath.Peek()))
{
finalPath.Push(tempPath.Pop());
}
start = (int)tempPath.Peek();
}
else
{
start = i;
break;
}
}
}
}
}
catch
{
Console.WriteLine("Print: ");
}
finally
{
foreach (object o in finalPath)
{
Console.Write(o.ToString() + "---->");
}
}
Console.ReadKey();
}