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: