Language: C++
/* UVa 11987 - Almost Union-Find To build using Visucal Studio 2012: cl -EHsc UVa_11987_Almost_Union-Find.cpp */ #include <cstdio> const int n_max = 100000 + 1; class almost_union_find { public: void make_set(int i); int find_set(int i) const; void move(int i, int j); void do_union(int i, int j); int size(int i) const; long long sum(int i) const; private: struct set { int size_; int head_, tail_; }; struct element { int set_; int prev_, next_; }; int n_; set sets_[n_max]; element elements_[n_max]; }; void almost_union_find::make_set(int i) { sets_[i].size_ = 1; sets_[i].head_ = sets_[i].tail_ = i; elements_[i].set_ = i; elements_[i].prev_ = elements_[i].next_ = -1; } int almost_union_find::find_set(int i) const { return sets_[elements_[i].set_].head_; } void almost_union_find::do_union(int i, int j) { if (elements_[i].set_ == elements_[j].set_) return; set &si = sets_[elements_[i].set_], &sj = sets_[elements_[j].set_]; if (si.size_ >= sj.size_) { si.size_ += sj.size_; elements_[sj.head_].prev_ = si.tail_; elements_[si.tail_].next_ = sj.head_; si.tail_ = sj.tail_; for (int next = sj.head_; next != -1; next = elements_[next].next_) elements_[next].set_ = elements_[i].set_; } else { sj.size_ += si.size_; elements_[si.head_].prev_ = sj.tail_; elements_[sj.tail_].next_ = si.head_; sj.tail_ = si.tail_; for (int next = si.head_; next != -1; next = elements_[next].next_) elements_[next].set_ = elements_[j].set_; } } void almost_union_find::move(int i, int j) { if (elements_[i].set_ == elements_[j].set_) return; int prev, next; set &si = sets_[elements_[i].set_], &sj = sets_[elements_[j].set_]; if (si.size_ > 1) { si.size_--; if (si.head_ == i) { next = elements_[i].next_; si.head_ = next; elements_[next].prev_ = -1; } else if (si.tail_ == i) { prev = elements_[i].prev_; si.tail_ = prev; elements_[prev].next_ = -1; } else { prev = elements_[i].prev_, next = elements_[i].next_; elements_[prev].next_ = next, elements_[next].prev_ = prev; } } sj.size_++; elements_[i].set_ = elements_[j].set_; elements_[sj.tail_].next_ = i; elements_[i].prev_ = sj.tail_, elements_[i].next_ = -1; sj.tail_ = i; } int almost_union_find::size(int i) const { return sets_[elements_[i].set_].size_; } long long almost_union_find::sum(int i) const { long long s = 0; for (int next = sets_[elements_[i].set_].head_; next != -1; next = elements_[next].next_) s += next; return s; } almost_union_find auf; int main() { int n, m; while (scanf("%d %d", &n, &m) != EOF) { for (int i = 1; i <= n; i++) auf.make_set(i); while (m--) { int c, p, q; scanf("%d", &c); switch (c) { case 1: scanf("%d %d", &p, &q); auf.do_union(p, q); break; case 2: scanf("%d %d", &p, &q); auf.move(p, q); break; case 3: scanf("%d", &p); printf("%d %lld\n", auf.size(p), auf.sum(p)); break; } } } return 0; }