C++
 Computer >> コンピューター >  >> プログラミング >> C++

C++で各頂点の指定された次数からグラフを生成する方法

頂点のリストと、それぞれの頂点に割り当てられた次数(degree)が与えられたとき、その次数列から無向グラフを生成することを考えます。ここで生成するグラフには、自己ループや多重辺は含まれないものとします。

例えば、次数列が [2, 2, 1, 1] の場合、生成できるグラフは次の図のようになります。

C++で各頂点の指定された次数からグラフを生成する方法

アルゴリズムの手順

この問題は、貪欲法(グリーディ法)の考え方を使って解くことができます。具体的な手順は以下の通りです。

  • グラフの構造を保存するための隣接行列 adj を定義し、すべての要素を 0 で初期化します。

  • 各頂点 i について、それより後ろの頂点 j を順に調べます。

    • 頂点 i と頂点 j の次数がどちらも 0 より大きい場合、両者の次数を 1 ずつ減らし、隣接行列上で i と j を結ぶ辺を設定します(adj[i][j] = adj[j][i] = 1)。

  • すべての頂点について処理が完了したら、隣接行列を整形して表示します。

サンプルコード

#include <iostream>
#include <iomanip>
using namespace std;

void generateGraph(int vert_degree[], int n) {
    int adj_mat[n][n];
    // 隣接行列を0で初期化
    for(int i = 0; i<n; i++){
        for(int j = 0; j < n; j++){
            adj_mat[i][j] = 0;
        }
    }
    // 次数が残っている頂点同士を辺で結ぶ
    for (int i = 0; i < n; i++) {
        for (int j = i + 1; j < n; j++) {
            if (vert_degree[i] > 0 && vert_degree[j] > 0) {
                vert_degree[i]--; vert_degree[j]--;
                adj_mat[i][j] = adj_mat[j][i] = 1;
            }
        }
    }
    // 隣接行列を見やすい形式で表示
    cout << endl << setw(3) << " ";
    for (int i = 0; i < n; i++)
        cout << setw(3) << "(" << i << ")";
    cout << endl << endl;
    for (int i = 0; i < n; i++) {
        cout << setw(4) << "(" << i << ")";
        for (int j = 0; j < n; j++)
            cout << setw(5) << adj_mat[i][j];
        cout << endl;
    }
}

int main() {
    int vert_degree[] = { 2, 2, 1, 1, 1 };
    int n = sizeof(vert_degree) / sizeof(vert_degree[0]);
    generateGraph(vert_degree, n);
}

出力結果

     (0)  (1)  (2)  (3)  (4)

(0)    0    1    1    0    0
(1)    1    0    0    1    0
(2)    1    0    0    0    0
(3)    0    1    0    0    0
(4)    0    0    0    0    0

補足:この手法の注意点

上記の貪欲なアプローチはシンプルで理解しやすい一方、与えられた次数列が「グラフィカル(実際のグラフとして構成可能)」でない場合、正しいグラフを生成できないことがあります。次数列が有効かどうかを厳密に判定したい場合は、Havel–Hakimi アルゴリズムErdős–Gallai の定理を利用するとよいでしょう。また、計算量は頂点ペアを二重ループで走査するため O(n²) となり、頂点数が多い場合でも比較的効率的に動作します。

  1. C++で始点から終点までのすべての経路を出力する方法|深さ優先探索(DFS)による実装

    この記事では、有向グラフが与えられたときに、始点(ソース)から終点(デスティネーション)までのすべての経路を出力する問題を、C++で解く方法を解説します。有向グラフとは?有向グラフとは、各辺に向きが定められており、頂点Aから頂点Bへと一方向に進むことができるグラフのことです。逆向き(BからA)には、対応する逆向きの辺が存在しない限り移動できません。問題の例具体例を使って問題を理解しましょう。下図のようなグラフを考えます。始点を「K」、終点を「P」とした場合の出力は次のようになります。出力:K -> T -> Y -> A -> P K -> T -> Y -

  2. C++で無向グラフ内のすべてのサイクルの長さの積を求める方法

    本記事では、無向かつ非重み付きグラフが入力として与えられたとき、そのグラフ内に形成されるすべてのサイクルの長さ(頂点数)の積を求め、結果を出力する方法を解説します。具体例入力例1この図では合計8つのノードがあり、そのうちノード1、6、3、5、8の5つがサイクルを形成しています。残りのノードはサイクルに含まれません。したがって、サイクルの長さは5であり、積は5となります。入力例2この図では合計12のノードがあり、そのうち11個(5個+6個)のノードが2つのサイクルを形成しています。1つ目はノード1、6、3、5、8からなるサイクル、2つ目はノード9、4、10、11、22、12からなるサイクルです。