質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

1回答

665閲覧

幅優先検索の疑問点について

jaogjig

総合スコア21

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

1クリップ

投稿2022/09/06 09:35

編集2022/09/06 10:37

前提

入力として Nは頂点数6M辺数7とする
A[100009]配列
B[100009]配列
この二つは隣接しているリストとする
「vector<int> G[100009];」のGは頂点の番号を表している。
このようにA[i]B[i]に以下のように入力例とする
G1:{2,3}
G2:{1,4,5}
G3{1,4}
G4{2,3,6}
G5{2,6}
G6{5,4}
2列3行の四角形になります。

手順としては
手順1.全ての頂点を白色で塗る。
手順2.キューQに頂点1を追加する。dist[1]=0とし、頂点1を灰色で塗る。
手順3.キューQが空になるまで、以下の操作を繰り返す。
Qの先頭の要素posを調べる。
Qの先頭の要素を取り出す。
頂点posに隣接し白色で塗られている頂点nexについて、dist[nex]をdist[pos]+1
に更新し、Qにnexを追加する。キューに頂点を追加する際には、その頂点を灰色に塗る。
出力としては
頂点1から各頂点までの最短経路長を求める

発生している問題・エラーメッセージ

// 幅優先探索 while (!Q.empty()) { int pos = Q.front(); // Q の先頭を調べる(操作 2) Q.pop(); // Q の先頭を取り出す(操作 3) for (int i = 0; i < (int)G[pos].size(); i++) { int nex = G[pos][i]; cout<<G[pos][i]<<":"<<endl; if (dist[nex] == -1) { dist[nex] = dist[pos] + 1; cout<<dist[nex]<<"@"<<endl; Q.push(nex); // Q に nex を追加(操作 1) } } }

わからないところが2つあります。
1つ目は
「cout<<G[pos][i]<<":"<<endl;」の部分の出力を出力
2: ...*14と続いているのですが[pos][i]と二つの配列があるのに一つの数字しか出力されません。理由が分かりません。

2つ目は
.size()はG[]配列では[123456]と6要素しかないはずなのに14回for文が回っています。A[]B[]の合計が14個あるので14回回ると考えていますが、配列が具体的にどうなるのかイメージがつきません。
ご教授お願いします。

該当のソースコード

#include <iostream> #include <vector> #include <queue> using namespace std; int N, M, A[100009], B[100009]; int dist[100009]; vector<int> G[100009]; int main() { // 入力 cin >> N >> M; for (int i = 1; i <= M; i++) { cin >> A[i] >> B[i]; G[A[i]].push_back(B[i]); G[B[i]].push_back(A[i]); } // 幅優先探索の初期化(dist[i]=-1 のとき、未到達の白色頂点である) for (int i = 1; i <= N; i++) dist[i] = -1; queue<int> Q; // キュー Q を定義する Q.push(1); dist[1] = 0; // Q に 1 を追加(操作 1) // 幅優先探索 while (!Q.empty()) { int pos = Q.front(); // Q の先頭を調べる(操作 2) Q.pop(); // Q の先頭を取り出す(操作 3) for (int i = 0; i < (int)G[pos].size(); i++) { int nex = G[pos][i]; if (dist[nex] == -1) { dist[nex] = dist[pos] + 1; Q.push(nex); // Q に nex を追加(操作 1) } } } // 頂点 1 から各頂点までの最短距離を出力 for (int i = 1; i <= N; i++) cout << dist[i] << endl; return 0; }

試したこと

// 幅優先探索 while (!Q.empty()) { int pos = Q.front(); // Q の先頭を調べる(操作 2) Q.pop(); // Q の先頭を取り出す(操作 3) for (int i = 0; i < (int)G[pos].size(); i++) { int nex = G[pos][i];// cout<<G[pos][i]<<":"<<endl;//ここを出力してどこがわからないか試した

test

1入力 26 37 4 51 62 7 81 93 10 11 12 132 145 15 16 173 184 19 204 212 22 23 244 256 26 27 285 296 30 316 324 33 34 35出力 362: 373: 381: 395: 404: 411: 424: 432: 446: 453: 462: 476: 484: 495: 50 510 521 531 542 552 56

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

6 7 の入力の後、辺の読み込みを 7組しかしていません。入力データは 14 行ありますよ。

追記
G[pos][i] の値を表示したければ、次のようにすればよいでしょう。

C++

1 cout << pos << ":"; // ★ 2 for (int i = 0; i < (int)G[pos].size(); i++) { 3 int nex = G[pos][i]; 4 cout << " " << nex; // ★ 5 if (dist[nex] == -1) { 6 dist[nex] = dist[pos] + 1; 7 Q.push(nex); // Q に nex を追加(操作 1) 8 } 9 } 10 cout << endl; // ★

追記2

2: ...*14と続いているのですが

2:/3:/ ... 4:/5:/ (ただし / は改行) と続いています。

[pos][i]と二つの配列があるのに

2つの添字がありますが、配列は 1つの G だけです。

.size()はG[]配列では[123456]と6要素しかないはずなのに14回for文が回っています。

G の要素数は 100009 ですが、使っているのは G[1]~G[6] の 6個だけです。
G は vector<int> を要素とする配列です。

G[1] = {2, 3} G[1].size() = 2 G[1][0] = 2, G[1][1] = 3 G[2] = {1, 5, 4} G[2].size() = 3 G[2][0] = 1, G[2][1] = 5, G[2][2] = 4 G[3] = {1, 4} G[3].size() = 2 G[3][0] = 1, G[3][1] = 4 G[4] = {3, 2, 6} G[4].size() = 3 G[4][0] = 3, G[4][1] = 2, G[4][2] = 6 G[5] = {2, 6} G[5].size() = 2 G[5][0] = 2, G[5][1] = 6 G[6] = {4, 5} G[6].size() = 2 G[6][0] = 4, G[6][1] = 5

for文は G[pos].size() の合計の 14回まわっています。

ところで、100009 という数字はどこから来ているのですか?
C++ では vector が使えるのですから、必要な個数だけ用意すればいいでしょう。

C++

1#include <iostream> 2#include <vector> 3#include <queue> 4using namespace std; 5 6int main() 7{ 8 int N, M, A, B; 9 cin >> N >> M; 10 vector<int> dist(N+1, -1); // 初期値: -1(未到達) 11 vector<vector<int>> G(N+1); 12 for (int i = 0; i < M; i++) { 13 cin >> A >> B; 14 G[A].push_back(B); 15 G[B].push_back(A); 16 } 17 queue<int> Q; // 距離が求まった頂点 18 dist[1] = 0; // 頂点1 は距離 0 19 Q.push(1); // 頂点1 は距離確定 20 21 while (!Q.empty()) { 22 int pos = Q.front(); // Q の先頭を調べる(操作 2) 23 Q.pop(); 24 cout << "G[" << pos << "]:"; 25 for (int i = 0; i < (int)G[pos].size(); i++) { 26 int nex = G[pos][i]; 27 cout << " " << nex; 28 if (dist[nex] == -1) { 29 dist[nex] = dist[pos] + 1; 30 Q.push(nex); // Q に nex を追加(操作 1) 31 } 32 } 33 cout << endl; 34 } 35 // 頂点 1 から各頂点までの最短距離を出力 36 for (int i = 1; i <= N; i++) cout << dist[i] << endl; 37}

入力

6 7 1 2 1 3 2 5 3 4 4 2 4 6 5 6

実行結果

G[1]: 2 3 G[2]: 1 5 4 G[3]: 1 4 G[5]: 2 6 G[4]: 3 2 6 G[6]: 4 5 0 1 1 2 2 3

投稿2022/09/06 10:16

編集2022/09/08 14:03
kazuma-s

総合スコア8224

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

jaogjig

2022/09/06 10:33

回答ありがとうございます。 直したら期待通りの出力になりました。修正しておきます 次の質問なのですが for (int i = 0; i < (int)G[pos].size(); i++) { int nex = G[pos][i]; cout<<G[pos][i]<<":"<<endl; ここの出力がなぜ(2:のような)一つの数字になるのでしょうか
jaogjig

2022/09/08 11:42 編集

int nex = G[pos][i]; この[i]の部分は何を表していますか またG[pos][i];を日本語にするとどのようになりますか どういう理屈で下のようになりますか 2、3 154 14 26 326 45
kazuma-s

2022/09/08 14:12 編集

G が「vector<int> の配列」なので、 G[pos] はその配列の pos 番目の要素です。 G[pos] は vector<int>、すなわち「int の vector」なので、 G[pos][i] は、その vector の i 番目の要素です。 G[pos][i] の値の全部を回答の追記2 に追加しました。
jaogjig

2022/09/09 08:21

G[pos][i]は 具体的にいうと G[1](G配列)の中の[0]番目の要素のデータ(.size)ということであっていますか
kazuma-s

2022/09/09 09:10

G[pos][i] は具体的にいうと、配列G の pos番目の要素である vector<int> の i番目の要素で int です。 pos が 1 で、i が 0 のとき、G[pos][i] は 配列G の 1番目の要素の 0番目の要素です。 size は vector<int> のメンバ関数で、G[pos].size() を呼び出すと、G[pos] の中の要素数を返します。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問