Problem p03855 (C++)

Buggy submission (status: Runtime Error):
#include <algorithm>
#include <iostream>
#include <map>
#include <vector>
using namespace std;
#define MAX_N 200

// Union-Findtree
struct UF {
  int par[MAX_N];  // 親
  int Rank[MAX_N]; // 木の深さ

  // 初期化
  void init(int n) {
    for (int i = 0; i < n; i++) {
      par[i] = i;
      Rank[i] = 0;
    }
  }

  // 木の根を求める
  int find(int x) {
    if (par[x] == x) {
      return x;
    } else {
      return par[x] = find(par[x]);
    }
  }

  // xとyの属する集合を併合
  void unite(int x, int y) {
    x = find(x);
    y = find(y);
    if (x == y)
      return; // すでに同じ集合に属している

    if (Rank[x] < Rank[y]) { // 高さが小さい方を下に
      par[x] = y;
    } else {
      par[y] = x;
      if (Rank[x] == Rank[y])
        Rank[x]++; // 同じだとrankが変わらないままになるので増やす（それ以外は大きい方のrankが採用される）
    }
  }

  // xとyが同じ集合に属するかを判定
  bool same(int x, int y) { return find(x) == find(y); }
};

int main() {
  int n, k, l;
  cin >> n >> k >> l;
  vector<int> p(k), q(k), r(l), s(l);
  UF tree1, tree2;
  tree1.init(n);
  tree2.init(n);
  int a, b;
  for (int i = 0; i < k; ++i) {
    cin >> a >> b;
    a--;
    b--;
    p[i] = a;
    q[i] = b;
  }
  for (int i = 0; i < l; ++i) {
    cin >> a >> b;
    a--;
    b--;
    r[i] = a;
    s[i] = b;
  }
  for (int i = 0; i < k; ++i)
    tree1.unite(p[i], q[i]);
  for (int i = 0; i < l; ++i)
    tree2.unite(r[i], s[i]);
  map<pair<int, int>, int> count;
  for (int i = 0; i < n; ++i) {
    ++count[make_pair(tree1.find(i), tree2.find(i))];
  }
  vector<int> ans(n);
  for (int i = 0; i < n; ++i) {
    ans[i] = count[make_pair(tree1.find(i), tree2.find(i))];
  }
  for (int i = 0; i < n; ++i) {
    if (i)
      cout << " ";
    cout << ans[i];
  }
  cout << endl;
  return 0;
}

Fixed submission:
#include <algorithm>
#include <iostream>
#include <map>
#include <vector>
using namespace std;
#define MAX_N 200005

// Union-Findtree
struct UF {
  int par[MAX_N];  // 親
  int Rank[MAX_N]; // 木の深さ

  // 初期化
  void init(int n) {
    for (int i = 0; i < n; i++) {
      par[i] = i;
      Rank[i] = 0;
    }
  }

  // 木の根を求める
  int find(int x) {
    if (par[x] == x) {
      return x;
    } else {
      return par[x] = find(par[x]);
    }
  }

  // xとyの属する集合を併合
  void unite(int x, int y) {
    x = find(x);
    y = find(y);
    if (x == y)
      return; // すでに同じ集合に属している

    if (Rank[x] < Rank[y]) { // 高さが小さい方を下に
      par[x] = y;
    } else {
      par[y] = x;
      if (Rank[x] == Rank[y])
        Rank[x]++; // 同じだとrankが変わらないままになるので増やす（それ以外は大きい方のrankが採用される）
    }
  }

  // xとyが同じ集合に属するかを判定
  bool same(int x, int y) { return find(x) == find(y); }
};

int main() {
  int n, k, l;
  cin >> n >> k >> l;
  vector<int> p(k), q(k), r(l), s(l);
  UF tree1, tree2;
  tree1.init(n);
  tree2.init(n);
  int a, b;
  for (int i = 0; i < k; ++i) {
    cin >> a >> b;
    a--;
    b--;
    p[i] = a;
    q[i] = b;
  }
  for (int i = 0; i < l; ++i) {
    cin >> a >> b;
    a--;
    b--;
    r[i] = a;
    s[i] = b;
  }
  for (int i = 0; i < k; ++i)
    tree1.unite(p[i], q[i]);
  for (int i = 0; i < l; ++i)
    tree2.unite(r[i], s[i]);
  map<pair<int, int>, int> count;
  for (int i = 0; i < n; ++i) {
    ++count[make_pair(tree1.find(i), tree2.find(i))];
  }
  vector<int> ans(n);
  for (int i = 0; i < n; ++i) {
    ans[i] = count[make_pair(tree1.find(i), tree2.find(i))];
  }
  for (int i = 0; i < n; ++i) {
    if (i)
      cout << " ";
    cout << ans[i];
  }
  cout << endl;
  return 0;
}