グラフアルゴリズムシリーズにおける深さ優先探索

グラフアルゴリズムシリーズにおける深さ優先探索

[[396433]]

この記事はWeChatの公開アカウント「Beta Learns JAVA」から転載したもので、著者はSilently9527です。この記事を転載する場合は、Beta Learning JAVA パブリック アカウントにお問い合わせください。

前回の記事では、深さ優先探索と、深さ優先探索を使用してグラフ内のパスを見つける方法について学習しました。この記事では、深さ優先探索アルゴリズムの他の適用シナリオについて引き続き学習します。

接続されたコンポーネント

グラフからすべての接続コンポーネントを見つけることも、深さ優先探索の応用シナリオです。連結成分とは何でしょうか? この定義は、前回の記事「ソーシャル ネットワークで 2 人の人が友人であるかどうかを検出する方法 (結合検索アルゴリズム)」で説明しました。

この記事では、結合検索アルゴリズムによって接続性チェックを実装します。この記事では、深さ優先探索法を使用して、グラフ内のすべての接続コンポーネントを検索します。

接続コンポーネントのAPI定義

  1. パブリッククラスDepthFirstCC {
  2. パブリックDepthFirstCC(グラフ グラフ);
  3.      
  4. public boolean connected( int v, int w); // 2つの頂点が接続されているかどうかを確認します
  5.  
  6. 公共 整数  count (); //接続されたコンポーネントの合計数をカウントします
  7.  
  8. 公共  int id( int v); //頂点vが位置する接続コンポーネントの識別子
  9. }

接続コンポーネントのAPI実装

以前と同様に、頂点をスキャンしない場合はマークする必要があるため、marked[]配列を定義する必要があります。

グラフ内の連結成分の総数を数えるには、変数countを定義する必要がある。

2 つの頂点が接続されているかどうかを判断するには、接続されている頂点の対応する識別値を同じ値として記録する必要があります。接続メソッドを呼び出すときに、2 つの頂点の識別値を直接取り出して比較します。同じ場合は接続されており、そうでない場合は接続されていません。

使用する識別値はカウント値です。各頂点には識別値を格納する必要があるため、ids[]配列も必要です。

  1. パブリッククラスDepthFirstCC {
  2. プライベートブール値 marked[];
  3. プライベートint  カウント;
  4. プライベートint [] ids;
  5.  
  6. パブリックDepthFirstCC(グラフグラフ) {
  7. this.marked = 新しいブール値[graph.V()];
  8. this.ids = 新しいint [graph.V()];
  9.  
  10. ( int v = 0; v < graph.V(); v++)の場合{
  11. if (!this.marked[v]) {
  12. dfs(グラフ, v);
  13. カウント++;
  14. }
  15. }
  16. }
  17.  
  18. プライベートvoid dfs(グラフグラフ、 int v) {
  19. this.marked[v] = true ;
  20. this.ids[v] =カウント;
  21. ( int w : graph.adj(v))の場合{
  22. if (!this.marked[w]) {
  23. dfs(グラフ, w);
  24. }
  25. }
  26. }
  27.  
  28. パブリックブール接続( int v, int w) {
  29. id(v) == id(w)を返します
  30. }
  31.  
  32. 公共 整数 カウント(){
  33. 戻る カウント;
  34. }
  35.  
  36. 公共  int id( int v) {
  37. ids[v]を返します
  38. }
  39.  
  40. }

ユニットテスト

このようなグラフを構築すると、連結成分の総数は3になるはずです。

  1. @テスト
  2. パブリックボイドテスト(){
  3. グラフ graph = new Graph(10);
  4. グラフにエッジを追加します。(0, 1);
  5. グラフにエッジを追加します(0, 2);
  6. グラフにエッジを追加します(0, 5);
  7. グラフにエッジを追加します。(1, 3);
  8. グラフにエッジを追加します。
  9. グラフにエッジを追加します(4, 3);
  10. グラフにエッジを追加します(5, 3);
  11.  
  12. グラフにエッジを追加します(6, 7);
  13.  
  14. グラフにエッジを追加します(8, 9);
  15.  
  16. DepthFirstCC cc = 新しい DepthFirstCC(グラフ);
  17.  
  18. System.out.println (cc.connected(0,5)) ;
  19. System.out.println (cc.connected(1,2)) ;
  20.  
  21. System.out.println ( cc.count ()) ;
  22. }

深さ優先探索に基づく接続性チェックは、理論的には、以前に実装された和集合検索アルゴリズムよりも高速です。これは、深さ優先探索で実装された接続性チェックは一定時間で完了することが保証されるのに対し、和集合検索アルゴリズムではそれができないためです。

しかし、union-find にも独自の利点があります。グラフを完全に構築して表現する必要がなく、さらに重要なことに、union-find アルゴリズムは動的にノードを追加します。

無向グラフにサイクルがあるかどうかを確認する

実装の複雑さを軽減するために、グラフには自己ループや平行エッジが存在しないものと仮定します。

頂点 v から始まるループがある場合、頂点 v から始まる接続コンポーネント内の頂点の隣接頂点が v であることを意味し、検索プロセス中に頂点 v が必ず再び発生します。

実装のアイデア:

  1. 検索された各頂点をマークする
  2. マークされた頂点に遭遇した場合、グラフ内にすでにサイクルが存在することを意味します。
  3. グラフは無向グラフであるため、vw が連結されている場合、頂点 v の隣接リストには w が含まれ、w の隣接リストにも v が含まれますが、それらはサイクルを形成しないため、この状況を除外する必要があります。
  1. パブリッククラスCycle{
  2. プライベートブール値 marked[];
  3. プライベートブールハッシュサイクル;
  4.  
  5. パブリックCycle(グラフ グラフ) {
  6. this.marked = 新しいブール値[graph.V()];
  7. ( int s = 0; s < graph.V(); s++)の場合{
  8. if (!this.marked[s]) {
  9. dfs(グラフ, s, s);
  10. }
  11. }
  12. }
  13.  
  14. プライベートvoid dfs(グラフグラフ、 int v、 int pV) {
  15. this.marked[v] = true ;
  16. ( int w : graph.adj(v))の場合{
  17. if (!this.marked[w]) {
  18. this.dfs(グラフ、w、v);
  19. }そうでない場合 (w != pV) {
  20. this.hashCycle = true ;
  21. 戻る;
  22. }
  23. }
  24. }
  25.  
  26. パブリックブールhasCycle() {
  27. ハッシュサイクルを返します
  28. }
  29. }

メソッド dfs のパラメーター v は検索する頂点を表し、pV は v に到達する頂点を表します。したがって、v の隣接リストにマークされた頂点があり、この頂点が v に到達する頂点と等しくない場合、グラフにサイクルが存在します。

無向グラフが二部グラフであるかどうかを確認する

二部グラフとは何ですか? グラフ内の各辺は、以下に示すように、異なる部分に属する頂点を接続します。

赤いノードは 1 つのセットを表し、白いノードは別のセットを表し、各エッジで接続された 2 つの頂点は異なるセットに属します。

実際の例で理解するのは簡単です。映画と俳優の関係。映画は頂点であり、俳優は頂点です。映画と俳優の間には直接のエッジはなく、俳優の間にも直接のエッジはありません。これは二部グラフです。

  1. パブリッククラスTwoColorGraph {
  2. プライベートブール値 twoColor = true ;
  3. プライベートブール値[]がマークされています。
  4. プライベートブール値[] color;
  5.  
  6. パブリックTwoColorGraph(グラフグラフ) {
  7. this.marked = 新しいブール値[graph.V()];
  8. this.color = 新しいブール値[graph.V()];
  9.  
  10. ( int v = 0; v < graph.V(); v++)の場合{
  11. if (!this.marked[v]) {
  12. dfs(グラフ, v);
  13. }
  14. }
  15. }
  16.  
  17. プライベートvoid dfs(グラフグラフ、 int v) {
  18. this.marked[v] = true ;
  19. ( int w : graph.adj(v))の場合{
  20. if (!this.marked[w]) {
  21. this.color[w] = !this.color[v];
  22. dfs(グラフ, w);
  23. }そうでなければ(this.color[w] == this.color[v]){
  24. this.twoColor = false ;
  25. 戻る;
  26. }
  27. }
  28. }
  29.  
  30. パブリックブール値isTwoColor() {
  31. twoColorを返します
  32. }
  33. }

この記事のすべてのソースコードは、github リポジトリに保存されています: https://github.com/silently9527/JavaCore

<<:  新しい3Dバイオプリンティング技術は皮膚と骨の損傷を同時に修復できる

>>:  チューリング賞受賞者:人工知能を実装したものは、もはや人工知能とは呼ばれない

ブログ    
ブログ    
ブログ    
ブログ    

推薦する

...

[ディープラーニングシリーズ] PaddlePaddleとTensorflowによる画像分類

先月は、ディープラーニングにおける「Hello World」であるMNIST画像認識を中心に、畳み込...

AIファイナンスブームの背後にはアリババとスタートアップ企業独自の狙いがある

中国の人工知能分野の二大大手であるMegvii TechnologyとSenseTime Techn...

宇宙の果ては「計算」だ! AI界の大物ウルフラム氏の最新スピーチ:LLMはコンピューティング空間を自律的に探索、シンギュラリティは今や到来

人工知能、宇宙、そしてあらゆるものを計算的に考えるにはどうすればよいでしょうか?最近、有名なイギリス...

...

人工知能にはどのような分野が含まれますか?どのように機能しますか?

現代の産業技術の発展により、私たちの生活は大きく改善されました。新しい家具が次々と登場しています。キ...

GoogleはBingの検索アルゴリズムを評価する研究開発チームを設立、創設者が戦いを監督

北京時間6月15日朝のニュースで、事情に詳しい関係者は、グーグルがマイクロソフトの新しい検索エンジン...

...

...

ChatGPTは個人のカスタマイズをサポートします!長いプロンプトに別れを告げ、まずは自己紹介をしましょう

この記事はAI新メディアQuantum Bit(公開アカウントID:QbitAI)より許可を得て転載...

...

ビジネス インテリジェンス戦略を成功させるための 8 つの重要な要素

ジャクソン氏は過去 8 年間にわたり、このプロジェクトを成熟させるために、社内の他の幹部と協力してき...

Stack Overflow が ChatGPT に対抗し、VS Code と連携する独自開発の生成 AI ツールをリリース

数日前、Stack Overflow コミュニティのトラフィックが大幅に減少したというニュースがあり...

DDLは第一の生産力です。科学的な説明があります。ネットユーザー:ビッグモデルで試してみましょう

年末です。大学生は期末試験の週で、労働者は KPI の達成に急いでいます。期限のない年末(DDL)は...