template class unionfind { unsigned n_sets; basedvector parent; public: unionfind (unsigned size); unionfind (const unionfind &u) : n_sets(u.n_sets), parent(u.parent) { } unionfind (copy, const unionfind &u) : n_sets(u.n_sets), parent(COPY, u.parent) { } unionfind (reader &r); ~unionfind () { } unsigned num_sets () const { return n_sets; } void clear (); void join (unsigned x, unsigned y); unsigned find (unsigned x); void write_self (writer &w) const; }; template unionfind::unionfind (unsigned size) : n_sets(size), parent(size) { for (unsigned i = 0; i < size; i ++) parent[i + B] = i + B; } template unionfind::unionfind (reader &r) { read (r, n_sets); read (r, parent); } template void unionfind::clear () { unsigned size = parent.size (); n_sets = size; for (unsigned i = 0; i < size; i ++) parent[i + B] = i + B; } template void unionfind::join (unsigned x, unsigned y) { unsigned xp = find (x), yp = find (y); if (xp != yp) { n_sets --; parent[yp] = xp; } } template unsigned unionfind::find (unsigned x) { unsigned p = parent[x]; while (parent[p] != p) p = parent[p]; while (x != p) { unsigned xp = parent[x]; parent[x] = p; x = xp; } return p; } template void unionfind::write_self (writer &w) const { write (w, n_sets); write (w, parent); }