2012-02-06 11 views
6

DAGが1つのソースであるとします。ソースからの完全なパスがn(つまり、nがすべてのシンクを占める)を通過するように、ノードnを見つけたいと思います。つまり、nのすべての後継者を削除した場合、すべてのパスはnで終了します。問題は、ノードがDAGで削除されたものとして段階的にマークされることです。ノードが削除マークされると、他のノードが上記のプロパティを満たすことができます。どのようにして効率よくこれを検出できますか?DAG内のドミネーターをインクリメンタルに検出

ボーナスポイントデータ構造は、ソースのそれぞれに別々に単一のソースのためのアルゴリズムを実行するよりも、より効率的な方法で複数のソースでこれを行うことができれば。

+1

これは、変化するグラフで徐々にカットを決定したいということですか?そして、あなたはそのようなすべてのノード(すべてのカット)を必要とするのか、それとも十分ですか? – jpalecek

+0

はい、これは別の言い方です:それが起こる直前(つまり、最後のノードが削除される直前に切断につながる直前)の検出です。 – Jules

+0

Re:編集:できればこのようなカットはすべて削除することをお勧めします。カットが比較的まれに起こるはずなので、それが起こると、他のカットを見つけるために遅いアルゴリズムを実行するのはあまりにも大したことではありません。 – Jules

答えて

3

このノードをトポロジ的に並べ替え、ノードの順序を確立します。各ノードについて、その値は、先行するすべてのノードからの出て行くエッジの数から、先行するすべてのノードおよび現在のノードへの入ってくるエッジの数を差し引いたものになります。 「dominator」ノードの値は常にゼロです。

ノードが「削除済み」とマークされた後、その先行ノードと後続ノードを優先キューに入れます。優先度は、トポロジカルなソート順によって決定されます。削除されたノードに続いて、すべてのノードの値を更新します(受信ノードの数を追加し、このノードの送信ノードの数を減算します)。優先度キュー内の先行ノードと「削除済み」ノードとの間の各ノードの(同じ順序で)デクリメント値と、優先度キュー内の後続ノードから始まる各ノードの増分値。ノードの値が0になると停止します。これは新しい「支配者」ノードです。すべての「dominator」ノードが必要な場合は、グラフの終わりまで続けます。複数のソースの場合について

delete(delNode): 
    for each predecessor in delNode.predecessors: queue.add(predecessor) 
    for each successor in delNode.successors: queue.add(successor) 
    for each node in DAG: 
    if queue.top.priority == node.priority > delNode.priority: 
     ++accumulator 

    node.value += accumulator 
    if node.value == 0: dominatorDetected(node) 

    if node.priority == delNode.priority: 
     accumulator += (delNode.predecessors.size - delNode.successors.size) 
     node.value = -1 

    if queue.top.priority == node.priority: 
     queue.pop() 
     if node.priority < delNode.priority: 
     --accumulator 

    if queue.empty: stop 

、同じアルゴリズムを使用するが、各ノードの「値」のリストを維持し、各ソースに対して1つの値が可能です。アルゴリズムの複雑さはO(Nodes * Sources)であり、各ソースの独立した検索と同じです。しかし、ベクトル化を使用すれば、プログラムをより効率的にすることができます。 「値」は、SIMD命令と並行して処理することができる。現代のコンパイラはこれを実現するために自動ベクトル化を行うかもしれません。

+0

頂点の値が支配者の場合にのみ、値が0であるという参照/証拠を与えることはできますか?私はなぜそれが本当であるかを理解していません[あるいは、私は 'value'の定義を正しく理解していません。 – amit

+1

Amit:私が探しているノードは、すべてのパスが通過するノードです。したがって、0辺はそのノードと平行になるはずです。入ってくるエッジ - ノードの前に出て行くエッジは、平行なエッジの数に等しい。 – Jules

+0

ありがとうございました!私は他の人に答えを書いて、回答をアップするための少しの時間を与えます、それから私はそれを受け入れます:)もう一度ありがとう! – Jules