web-dev-qa-db-ja.com

正の重みを持つ有向グラフで最短の長さのサイクルを見つけます

インタビューでこの質問をされましたが、まともな解決策を思い付くことができませんでした。それで、私は彼らに、すべてのサイクルを見つけて、最小の長さのサイクルを選ぶという素朴なアプローチを伝えました。

この問題の効率的な解決策は何か知りたいです。

16

簡単に変更できます Floyd-Warshallアルゴリズム 。 (グラフ理論にまったく精通していない場合は、それをチェックすることをお勧めします。たとえば、 アルゴリズムの概要 のコピーを入手します)。

従来、iごとに_path[i][i] = 0_を開始します。ただし、代わりに_path[i][i] = INFINITY_から開始できます。これらのゼロは計算に使用されなかったため、アルゴリズム自体には影響しません(パス_path[i][j]_は_k == i_または_k == j_では変更されないため)。

結局、_path[i][i]_は、iを通過する最短サイクルの長さです。したがって、すべてのiに対してmin(path[i][i])を見つける必要があります。また、サイクル自体(長さだけでなく)が必要な場合は、通常のパスで行われるのと同じように、アルゴリズムの実行中にkを記憶することで実行できます。

さらに、 ダイクストラのアルゴリズム を使用して、任意のノードを通過する最短のサイクルを見つけることもできます。この変更されたダイクストラをノードごとに実行すると、Floyd-Warshallの場合と同じ結果が得られます。また、各ダイクストラはO(n^2)であるため、全体的に同じO(n^3)の複雑さが得られます。

29
Nikita Rybak

擬似コードは、ダイクストラのアルゴリズムを単純に変更したものです。

for all u in V:
   for all v in V:
      path[u][v] = infinity

for all s in V:
   path[s][s] = 0
   H = makequeue (V) .. using pathvalues in path[s] array as keys
   while H is not empty:
      u = deletemin(H)
      for all edges (u,v) in E:
         if path[s][v] > path[s][u] + l(u, v) or path[s][s] == 0:
            path[s][v] = path[s][u] + l(u,v)
         decreaseKey(H, v)

lengthMinCycle = INT_MAX

for all v in V:
   if path[v][v] < lengthMinCycle & path[v][v] != 0 :
      lengthMinCycle = path[v][v]

if lengthMinCycle == INT_MAX:
   print(“The graph is acyclic.”)

else:
   print(“Length of minimum cycle is ”, lengthMinCycle)

時間計算量:O(| V | ^ 3)

6
excavator

質問がTSPと一致するため、巡回セールスマン問題に分枝限定アルゴリズムを使用することもできます。 http://lcm.csa.iisc.ernet.in/dsa/node187.html

0
shreyas_patel21

以下は、Floyd-Warshellアルゴリズムの簡単な変更です。

V = 4 
 INF = 999999 
 

def minimumCycleLength(graph): dist = [[0] * V for i in range(V)] for i in range(V): for j in range( V): dist [i] [j] = graph [i] [j]; for k in range(V): for i in range(V): for j in range(V): dist [i] [j] = min(dist [i] [j]、dist [i] [k] + dist [k] [j ]) length = INF for i in range(V): for j in range(V): length = min(length、dist [i ] [j]) 戻り長 graph = [ [INF, 1, 1,INF], [INF, INF, 1,INF], [1, INF, INF, 1], [INF, INF, INF, 1] ] length = minimumCycleLength(graph) print length
0
salman94

あなたがしなければならないことは、常に1である各ノードに別の重みを割り当てることです。次に、これらの重みを使用して、あるノードから同じノードへの最短経路アルゴリズムを実行します。ただし、中間パスを検討する際には、実際の重みが負のパスを無視する必要があります。

0
Manoj R
  • DFSを実行する
  • DFSの間、エッジのタイプを追跡します
  • エッジのタイプは、Tree EdgeBack EdgeDown Edge、およびParent Edgeです。
  • Back Edgeを取得したときに追跡し、長さを取得するための別のカウンターを用意します。

詳細については、Algorithms in C++ Part5 - Robert Sedgwickを参照してください

0
Avinash