今の時代なら確実に灰色 diff ですね。
問題概要
頂点数 、辺数 の単純無向グラフが与えられる。
頂点 と頂点 とを結ぶ辺は存在しないことがわかっている。
ある頂点 から 2 本の辺を辿ることで頂点 に到達できるかどうかを判定せよ。
制約
解法:グラフを表すデータ構造
グラフのデータ構造を活用する練習問題です!
グラフのことが何も分からないという方は、次の記事を読んでみてください。
グラフをデータ構造として表す場合は、たとえば下図のように、各頂点に隣接する頂点のリストを考えます。
これらの情報は、二次元配列 vector<vector<int>>
型の変数 G
を用いて管理できます。頂点 に隣接する頂点の集合は G[v]
と現せます。たとえば上図のグラフの場合、次のようになります。
G[0] = {5} G[1] = {3, 6} G[2] = {5, 7} G[3] = {0, 7} G[4] = {1, 2, 6} G[5] = {} G[6] = {7} G[7] = {0}
今回の問題
以上を踏まえて、今回の問題は次のように解釈できます。ただし、頂点番号は 0-indexed で考えることにします。
ある頂点 に対して、頂点 に隣接する頂点集合 G[v]
の中に、頂点 がともに含まれるとき "POSSIBLE" と答える
そうでないとき "IMPOSSIBLE" と答える
具体的には、次の解答例のように実装できます。
なお、各頂点 の隣接リスト G[v]
に格納されている要素数の総和は、辺数の 2 倍の となります (考えてみてください)。
よって、この解法の計算量は と評価できます。
コード
#include <bits/stdc++.h> using namespace std; int main() { int N, M; cin >> N >> M; vector<vector<int>> G(N); for (int i = 0; i < M; ++i) { int a, b; cin >> a >> b; --a, --b; // 0-indexed にする G[a].push_back(b); G[b].push_back(a); } bool res = false; for (int v = 1; v < N-1; ++v) { // G[v] が頂点 0, N-1 をともに含むか bool exist_zero = false, exist_n = false; for (auto v2 : G[v]) { if (v2 == 0) exist_zero = true; if (v2 == N-1) exist_n = true; } if (exist_zero && exist_n) res = true; } cout << (res ? "POSSIBLE" : "IMPOSSIBLE") << endl; }