web-dev-qa-db-ja.com

グラフ内のすべての切断されたサブグラフを見つける

不明な数の切断されたサブグラフを含むグラフがあります。それらすべてを見つけるための良いアルゴリズム(またはJavaライブラリ))は何ですか?

37
Ollie Glass

あなたが探しているものは、一般的に Flood Fill と呼ばれていると思います。 BFSとDFSのどちらを介してグラフをトラバースするかは、あなた次第です。

基本的には、ラベル付けされていない(色付けされていない)ノードを取得して、新しいラベルを割り当てます。そのノードに隣接するすべてのノードに同じラベルを割り当て、そのノードから到達可能なすべてのノードに同様に割り当てます。

ラベル付けできる到達可能なノードがなくなったら、ラベル付けされていない別のノードを選択することから始めます。この新しいノードにラベルが付いていないという事実は、以前のノードから到達できないため、別の切断されたコンポーネントにあることを意味します。

ラベル付けされていないノードがなくなると、使用しなければならない個別のラベルの数は、グラフのコンポーネントの数になります。各ノードのラベルは、どのノードがどのコンポーネントの一部であるかを示しています。

55
MAK

Java実装ではありませんが、おそらく誰かにとっては便利でしょう。Pythonでの実装方法は次のとおりです。

import networkx as nx
g = nx.Graph()
# add nodes/edges to graph
d = list(nx.connected_component_subgraphs(g))
# d contains disconnected subgraphs
# d[0] contains the biggest subgraph

詳細 ここ

17
Datageek

この質問には、十分に説明されていない側面がたくさんあるので、やや網羅的な回答をします。それにもかかわらず、テキストの壁を投稿する私の傾向。 :/これは宿題の質問または独学の質問であると想定しているので、正直な回答はしません。

グラフの接続を検出するための2つの基本的なアルゴリズムは、 深さ優先検索 および 幅優先検索 です。これらは実際に確認したい2つの出発点です。どちらの方法でも解決策は得られますが、方法は異なり、問題のかなり詳細な側面を考慮せずにどちらが「優れている」かを議論するのは困難です。しかし、先に進みましょう。

先に述べたように、あなたはいくつかの重要な詳細を省略しました、そして私はここでいくつかの可能性に触れます。

グラフは有向ですか、無向ですか?そして、「強い」という意味での接続性(この場合、oggyの回答を参照)を考慮しますか、それとも「弱い」という意味での接続性を考慮しますか?答えによっては、微妙に異なる方法でアルゴリズムにアプローチする必要があります。無向グラフの場合、弱い接続と強い接続は同等であるため、それはいいことです。ただし、アルゴリズムを実装または検索している間は、グラフの構造を常に意識する必要があります。

さらに、「サブグラフを見つける」(言い換え)とはどういう意味かという疑問があります。通常、グラフの接続性は決定の問題です。単に「1つの接続されたグラフがある」または「2つ以上のサブグラフがある(別名、切断されている)」ということです。そのためのアルゴリズムがあれば、最低限の本の仕事しか必要ありません。それは素晴らしいことです。 :)次のステップは、グラフのcountであり、文字通りそれらの数であり、そのブックワークもそれほど悪くありません。最後に、各サブグラフのノードのリストが必要になる場合があります。最後に、サブグラフ、エッジ、およびすべてを文字どおりにコピーすることもできます(したがって、戻り値の型は、各グラフが接続されていることを暗黙の不変条件としてグラフのリストになります)。これらの異なる結果タイプのいずれも、異なるアルゴリズムを必要としませんが、確かにブックワークへの異なるアプローチが必要です。

これらはすべて、かなり基本的な質問についてはばかげた量のように思えるかもしれませんが、このような単純なグラフの質問でさえ、関係するすべての側面を強調したいと思いました。一種のクリフハンガーとして、ランタイムやメモリの使用にはまだ触れていません。 :)-Agor

8
agorenst

JGraphT は、LGPLライセンスに基づいてライセンスされた、素晴らしいオープンソースのグラフ作成ライブラリです。私は過去にグラフを処理し、グラフ内のサイクルを検出するために使用しました。また、かなり使いやすく、 JGraph を使用してグラフを視覚化できます。

3
aperkins

(強く)接続されているすべてのコンポーネントを検索したいと思いますか?そのためには Tarjanのアルゴリズム (DFSの変形)を使用できます。

2
oggy

接続されているすべてのノードを見つけるための幅優先検索についてはどうですか?接続されたノードのリストを取得したら、すべてのノードのリストからこのリストを差し引きます。切断されたノードのリストが表示されます

1
MedicineMan

有向グラフの弱く接続されたすべてのサブグラフが必要な同様の問題に遭遇しました。私はそれについてブログに書いた here[〜#〜] jung [〜#〜] APIを使用して、2つのアプローチを比較しました。最初のアプローチは、問題を解決するためのテンプレートとして使用できます。

1
harschware