グラフの問題を解決しようとしています(宿題ではなく、単にスキルを練習するためです)。DAGが与えられます。ここで、は頂点のセット、はエッジです。グラフは隣接リストとして表されるため、はすべての接続を含むセットです。私の仕事は、各頂点から到達可能な頂点を見つけることです。私が使用するソリューションは複雑さを持ち、 推移的閉包を持ちますが、ブログで読むと高速になる可能性がありますが、方法は明らかになりませんでした。DAGの推移的閉包問題を解決する別の方法(より複雑な方法)を教えてもらえますか?
グラフの問題を解決しようとしています(宿題ではなく、単にスキルを練習するためです)。DAGが与えられます。ここで、は頂点のセット、はエッジです。グラフは隣接リストとして表されるため、はすべての接続を含むセットです。私の仕事は、各頂点から到達可能な頂点を見つけることです。私が使用するソリューションは複雑さを持ち、 推移的閉包を持ちますが、ブログで読むと高速になる可能性がありますが、方法は明らかになりませんでした。DAGの推移的閉包問題を解決する別の方法(より複雑な方法)を教えてもらえますか?
回答:
グラフが非周期的であるという事実により、この問題ははるかに単純になります。
トポロジカルソートでは、頂点順序付けを行うことができ、i < jの場合、v jからv iに戻るエッジはありません。リスト内のすべてのエッジが「進む」ように頂点をリストしました。
(分析を修正し、わずかに高速なアルゴリズムを提供するように編集)
最後の頂点から始めて、このリストを逆方向にたどっていきます。v nの推移閉包はそれ自体です。また、追加のV nとのエッジにすべての頂点の推移閉包にV N。
他の各頂点について、末尾から逆向きに移動し、最初にv iをそれ自身の推移閉包に追加し、次にv iの推移閉包内のすべてを、エッジがv iのすべての頂点の推移閉包に追加します。
実行時間は最悪の場合でn個の頂点の数M ∈ O (N 2)エッジの数。トポロジカルソートにはO (n + m )時間かかります。次に、逆方向パスで別のO (m n )作業を行います。リストを逆方向に進むと、各エッジに対して、nを加算する必要があります 誰かの推移的閉包の頂点。
全員の推移的閉包をビット配列で表すことにより、一定の係数で高速化できることに注意してください。しかなかったとします。次に、iが推移的閉包にある場合はビットiが1 で、それ以外の場合は0である単一の64ビットintを使用します。その後、我々はすべてのものを追加部分I「にsの推移閉包J s」は本当に速いです:私たちはちょうど取るのC jは | = C I。(バイナリOR演算。)
以下のため、あなたは配列でそれらを維持し、いくつかの算術演算を行う必要があるだろうが、それははるかに高速オブジェクトの集合よりなります。
また、非常に最悪の場合のbig はまだO (n 3)であることがわかりますが、実際にこれを破るには、もっと複雑なものが必要です。このアルゴリズムはまばらなグラフでも非常にうまく機能します。