Official
G - 連結/Connectivity Editorial by mechanicalpenciI
グラフの状態は隣接行列または隣接リストで持ち、状態を更新しながらクエリを順に処理していくことを考えます。
\(query\) の先頭の数字が \(1\) 、すなわち辺の変更クエリの時は該当する辺の状態を更新します。\(2\) 方向について変更する必要があることに注意してください。\(1\) 回あたりの計算量は隣接行列ならば \(O(1)\), 隣接リストならば \(O(N)\) で行う事が出来ます。
\(query\) の先頭の数字が \(2\)、すなわち頂点間が繋がっているかの探索クエリのときは 頂点 \(u\) から始めて DFS (深さ優先探索) または BFS (幅優先探索) などを行うことによって探索することができます。同じ頂点を \(2\) 度以上訪れないようにすることで、\(O(N^2)\) で行う事が出来ます。
よって、全体で \(O(N^2Q)\) でこの問題を解くことができました。\(N\leq 100\), \(Q\leq 10000\) ですので十分高速です。
c++による実装例 ( 隣接行列 +DFS ) :
#include <bits/stdc++.h>
using namespace std;
int n;
bool e[101][101] = {};
bool used[101];
bool dfs(int k,int v) {
used[k] = true;
if (k == v)return true;
for (int i = 1; i <= n; i++) {
if (e[k][i] && (!used[i]))if (dfs(i, v))return true;
}
return false;
}
int main(void) {
int q;
int t, u, v;
cin >> n >> q;
for (int i = 0; i < q; i++) {
cin >> t >> u >> v;
if (t == 1) {
e[u][v] = (!e[u][v]);
e[v][u] = (!e[v][u]);
}
else {
memset(used, 0, sizeof(used));
if (dfs(u, v))cout << "Yes" << endl;
else cout << "No" << endl;
}
}
return 0;
}
posted:
last update: