web-dev-qa-db-ja.com

2つのノードが接続されているかどうかを確認するにはどうすればよいですか?

これがNP完全問題に取り組んでいるのではないかと心配しています。誰かが私にそれがそうであるかどうかについて答えを与えることができることを願っています。そして、私はただ「はい」または「いいえ」よりも多くの答えを探しています。理由を知りたいのですが。 「これは基本的にこの問題 'x'であり、NP完全ではありません。(ウィキペディアのリンク)」と言えます。

(いいえ、これは宿題ではありません)

2つの点が任意の無向グラフで接続されているかどうかを判断する方法はありますか?例:次の

Well
  |
  |
  A
  |
  +--B--+--C--+--D--+
  |     |     |     |
  |     |     |     |
  E     F     G     H
  |     |     |     |
  |     |     |     |
  +--J--+--K--+--L--+
                    |
                    |
                    M
                    |
                    |
                  House

ポイントAからM(「I」なし)は、開閉可能な制御ポイント(天然ガスパイプのバルブなど)です。 '+'はノード(パイプTのような)であり、WellとHouseもノードであると思います。

井戸と家がまだ接続されているかどうか(他の制御点も閉じている可能性があります)、任意の制御点(Cなど)を閉じたかどうかを知りたいです。たとえば、B、K、Dが閉じている場合でも、A-E-J-F-C-G-L-Mを通るパスがあり、Cを閉じるとウェルとハウスが切断されます。もちろん; Dだけが閉じられた場合、Cだけを閉じてもハウスは切断されません。

別の言い方をすれば、Cはブリッジ/カットエッジ/峡部ですか?

各コントロールポイントをグラフ上の重みとして扱うことができます(開いている場合は0、閉じている場合は1)。次に、WellとHouseの間の最短パスを見つけます(結果> = 1は、それらが切断されたことを示します。最短パスを見つけるためのアルゴリズムを短絡する方法はいくつかあります(たとえば、1に達したらパスを破棄し、停止します)。井戸と家などを結ぶ経路ができたら検索します。もちろん、あきらめる前にチェックするホップの数に人為的な制限を設けることもできます。

誰かが以前にこの種の問題を分類したに違いありません、私はただ名前を逃しています。

17
BIBD

http://en.wikipedia.org/wiki/Dijkstra%27s_algorithm を参照してください。これは、グラフに関連するすべての問題のワンストップショップです。あなたの問題は実際には二次時間で解決できると思います。

6
Nick Gebbie

あなたの説明は、最短経路を見つけるのではなく、2つのノードが接続されているかどうかだけに関心があることを示しているようです。

2つのノードが接続されているかどうかを確認するのは比較的簡単です。

Create two sets of nodes:  toDoSet and doneSet
Add the source node to the toDoSet 
while (toDoSet is not empty) {
  Remove the first element from toDoSet
  Add it to doneSet
  foreach (node reachable from the removed node) {
    if (the node equals the destination node) {
       return success
    }
    if (the node is not in doneSet) {
       add it to toDoSet 
    }
  }
}

return failure.

ToDoSetとdoneSetにハッシュテーブルなどを使用する場合、これは線形アルゴリズムだと思います。

このアルゴリズムは基本的に、マークアンドスイープガベージコレクションのマーク部分であることに注意してください。

35
David Norman

この問題にはダイクストラのアルゴリズムは必要ありません。これは、不要なヒープを使用し、複雑さにlog(N)の係数を導入するためです。これは幅優先探索です。閉じたエッジをエッジとして含めないでください。

5
Gwildore

最短経路を見つける問題はNP完全ではありません。これは最短経路問題(元々は十分)と呼ばれ、さまざまなバリエーションを解くための アルゴリズム があります。

2つのノードが接続されているかどうかを判断する問題も、NP完全ではありません。いずれかのノードから開始する深さ優先探索を使用して、他のノードに接続されているかどうかを判断できます。

3
Bill the Lizard

nP完全ではなく、よく知られた解決策で解決- ダイクストラのアルゴリズム

2
Steven A. Lowe

私にはあなたが解決策に取り組んでいるように見えますが、私が問題を誤解した可能性があります。あなたが言うように、閉じたエッジ1を重みとして与える場合は、ダイクストラのアルゴリズムを適用することができます http://en.wikipedia.org/wiki/Dijkstra%27s_algorithm 。これにより、O(E * lg(V))の問題が解決するはずです。

2
torb

隣接行列があると仮定します。

bool[,] adj = new bool[n, n];

ここで、iとjの間にオープンパスがあり、bool [i、i] = falseの場合、bool [i、j] = trueです。

public bool pathExists(int[,] adj, int start, int end)
{
  List<int> visited = new List<int>();
  List<int> inprocess = new List<int>();
  inprocess.Add(start);

  while(inprocess.Count > 0)
  {
    int cur = inprocess[0];
    inprocess.RemoveAt(0);
    if(cur == end)
      return true;
    if(visited.Contains(cur))
      continue;
    visited.Add(cur);
    for(int i = 0; i < adj.Length; i++)
      if(adj[cur, i] && !visited.Contains(i) && !inprocess.Contains(i))
        inprocess.Add(i);
  }
  return false;
}

上記のアルゴリズムの再帰バージョン(Rubyで記述)は次のとおりです。

def connected? from, to, edges
  return true if from == to
  return true if edges.include?([from, to])
  return true if edges.include?([to, from])

  adjacent = edges.find_all { |e| e.include? from }
                  .flatten
                  .reject { |e| e == from }

  return adjacent.map do |a|
    connected? a, to, edges.reject { |e| e.include? from }
  end.any?
end
2
LeppyR64

2つのノードが接続されているかどうかを判断するだけでよい場合は、代わりにセットを使用できます。これは、グラフアルゴリズムよりも高速です。

  1. グラフ全体をエッジに分割します。各エッジをセットに追加します。
  2. 次の反復で、手順2で作成したエッジの2つの外側ノードの間にエッジを描画します。これは、元のエッジの元のセットに新しいノード(対応するセットを含む)を追加することを意味します。 (基本的にはマージを設定します)
  3. 探している2つのノードが同じセットになるまで、2を繰り返します。また、手順1の後にチェックを行う必要があります(2つのノードが隣接している場合に備えて)。

最初は、ノードはそれぞれのセットに含まれます。

o   o1   o   o   o   o   o   o2
 \ /     \ /     \ /     \ /
 o o     o o     o o     o o
   \     /         \     /
   o o o o         o o o o 
      \               /
       o o1 o o o o o o2

アルゴリズムが進行してセットをマージすると、入力が比較的半分になります。

上記の例では、o1とo2の間にパスがあるかどうかを確認していました。このパスは、すべてのエッジをマージした後の最後にのみ見つかりました。一部のグラフには個別のコンポーネント(切断されている)が含まれている場合があり、これにより、最後に1つのセットを設定することができなくなります。このような場合、このアルゴリズムを使用して、接続性をテストし、グラフ内のコンポーネントの数をカウントすることもできます。コンポーネントの数は、アルゴリズムが終了したときに取得できるセットの数です。

可能なグラフ(上のツリーの場合):

o-o1-o-o-o2
  |    |
  o    o
       |
       o
1
Adrian

間違いなくNP完全ではないという回答がありますが、これも非常に古い質問です。

ただし、問題を調べるための別のアプローチを提案します。これには互いに素なセットを使用できます。ほとんどの場合、特定のシナリオでは、このアプローチにより、グラフトラバーサルを実行するよりも時間が長くなります(これには、テストの大部分に対して一定時間が含まれます) )。ただし、ランクによる結合またはパス圧縮が使用されている場合、グラフの作成にはかなりの時間がかかる可能性があります。

データ構造について読むことができます ここ

0
metamemelord

ダイクストラ法はやり過ぎです! Aからの幅優先探索を使用して、到達したいノードを検索します。見つからない場合は接続されていません。複雑さは、検索ごとにO(nm)であり、ダイクストラよりも小さいです。

やや関連しているのは、最大フロー/最小カットの問題です。それを調べてください、それはあなたの問題に関連しているかもしれません。

0
rutger