AOJ 0321 Investigation of Club Activities
解法
union find 木を使うと楽?
union find の各集合がどのクラブに属するかを別に vector で持っておく.
a と b が同じ部活に所属している場合,マージするのだが違うクラブに属している(少なくともどちらか一方の集合のクラブの情報がない場合はセーフ)ならアウト.
c が部活 x に属しているとき,c の属する集合のクラブの情報と比べて違えばダメ.まだクラブの情報がないなら x を書き込む.
これを上から順番にやる.
ソースコード
#include <bits/stdc++.h> using namespace std; class union_find { public: union_find(int n) : par(n, -1) {} int root(int x) { return par[x] < 0 ? x : par[x] = root(par[x]); } bool same(int x, int y) { return root(x) == root(y); } void unite(int x, int y) { x = root(x), y = root(y); if(x == y) return; if(par[x] > par[y]) swap(x, y); par[x] += par[y]; par[y] = x; } private: vector<int> par; }; int main() { int n, m, k; cin >> n >> m >> k; union_find uf(n); vector<int> club(n, -1); int ans = 0; for(int i = 0; i < k; ++i) { int type; cin >> type; if(type == 1) { int a, b; cin >> a >> b; a--; b--; int ra = uf.root(a), rb = uf.root(b); if(club[ra] == -1 || club[rb] == -1 || club[ra] == club[rb]) { uf.unite(a, b); club[uf.root(a)] = max(club[ra], club[rb]); } else { ans = i + 1; break; } } else { int c, x; cin >> c >> x; c--; x--; if(club[uf.root(c)] == -1 || club[uf.root(c)] == x) { club[uf.root(c)] = x; } else { ans = i + 1; break; } } } cout << ans << endl; }
感想
PCK予選って解説無いんですかね?