私は自分の問題の効率的な解決策を見つけようとしています。G
100個のノード(各ノードに番号が付けられています)を含む正の重み付きグラフがあり、それが非循環グラフであると仮定しましょう。したがって、2、2、2、1などのエッジは存在できません。ノードのリストを取得しましたG
。グラフから10としましょう。これらの各ノードも配列にあるとしましょう。そのリストから、ノード1から100までの、それらのノードの少なくとも特定の(5つとしましょう)を通過する最短パスの総重みを見つける方法を探しています。
簡略化するために、0 ... 5の6つのノードを持つグラフを考えます。ノード1と4は、通過するように指定できるポイントとしてマークされています。既存のパスが0-1-2-5、0-3-4-5、および1-4であるとしましょう。ここで、3から4を除くすべてのエッジが5として重み付けされているとします。3から4は1として重み付けされます。最短パスアルゴリズムを実行すると、基本的にパス0-3-4-5が検出されます。指定されたポイントの最小量を指定して、量2を試してください。その後、アルゴリズムは15として重み付けされた0-1-4-5で実行されます。
私はこのように書きました
shortestPath(destinationNode, minAmount)
if(destinationNode == srcNode && minAmount < 1)
return 0
else if(destinationNode == srcNode && minAmount > 1)
return INFINITY
int destNo = destinationNode get number
int cost = INFINITY
for (int i = 0; i < destNo; i++)
if (d[i][destNo] != null)
int minimumAmountCount = minAmount;
for (int j = 0; j < marked.length(); j++)
if (marked[j] == i)
minimumAmountCount = minimumAmountCount - 1;
cost = MIN(cost, shortestPath(Node(i), minimumAmountCount);
return cost;
基本的に、宛先ノードとそのリストからのノードの最小数を使用して、このアルゴリズムを呼び出します。まず、これが再帰関数であり、停止ポイントが必要であることを確認します。これは、渡された宛先がソースノード(基本的にはノード#0)と等しい場合です。チェックする必要がある2番目のケースは、十分な量を訪問したかどうかです。したがって、1(0または負の数)未満の場合、十分なポイントを訪問し、ノード#0からノード#0までの距離が0になるため0を返します。十分な量を訪問しなかった場合は、無限大を返すため、アルゴリズムは他のパスを考慮します。
したがって、戻り部分が機能するためには、宛先ノードの番号を定義する必要があります(100のノードがあると考えると、最初の開始ではノード#99になります)、コストを無限大として初期化する必要があります。
次に、0(基本的にノード#0)から始まり、現在のノード番号までforループを実行します。これは、グラフに後方エッジがないためです。ノード番号を使用して、これらのノードに既存の重みがあるかどうかをマトリックスから確認します。存在する場合は、現在の最小量の変数を初期化し、ループを実行して、現在の宛先へのソースがマークされたノードのリストにあるかどうかを確認します。マークされている場合は、最小量を減らすだけです。
最後のステップでは、宛先を現在のソースとして、現在の最小量で変更して、関数を再度実行します。
しかし、ネストされたループの最悪の場合の複雑さはO(| Node | ^ 2)になり、完全な繰り返しはO(| Node | ^ 2 * | Edges |)になるという事実を考えると、非常に高価に見えます。それで、この問題の他の効率的な解決策はありますか?