Problem p03855 (C++)

Buggy submission (status: Runtime Error):
// #include <bits/stdc++.h>

#include <algorithm>
#include <complex>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <stack>
#include <string>
#include <unordered_map>
#include <vector>

#define INF 100000000000
#define rep(i, a) for (int i = 0; i < (a); i++)
using namespace std;

struct UnionFind {
  vector<long long int> par; // par[i] : iの親の番号
  vector<long long int> rnk; // root[i] : iの木のランク

  // コンストラクタ
  UnionFind(long long int n) : par(n), rnk(n) {
    // 木の初期化
    for (long long int i = 0; i < n; i++) {
      par[i] = i;
      rnk[i] = 1;
    }
  }

  // データxが属する木の根を再帰で取得
  long long int root(long long int x) {
    if (par[x] == x) {
      return x;
    } else {
      return par[x] = root(par[x]);
    }
  }

  // xとyが同じ木に属しているかを判定
  bool same(long long int x, long long int y) { return root(x) == root(y); }

  // xとyの木を併合
  void unite(long long int x, long long int y) {
    long long int rx = root(x); // xの根
    long long int ry = root(y); // yの根
    if (rx == ry)
      return; // 根が同じならそのまま

    if (rnk[rx] < rnk[ry]) {
      par[rx] = ry;
    } else {
      par[ry] = rx;
      if (rnk[rx] == rnk[ry])
        rnk[rx]++;
    }
  }
};

int main() {
  int n, k, l;
  cin >> n >> k >> l;

  UnionFind road(k), rail(l);
  int i;
  int p, q;
  for (i = 0; i < k; i++) {
    cin >> p >> q;
    road.unite(p - 1, q - 1);
  }
  for (i = 0; i < l; i++) {
    cin >> p >> q;
    rail.unite(p - 1, q - 1);
  }

  map<pair<int, int>, int> m;
  for (i = 0; i < n; i++) {
    m[make_pair(road.root(i), rail.root(i))]++;
  }

  for (i = 0; i < n; i++) {
    cout << m[make_pair(road.root(i), rail.root(i))] << endl;
  }
}

Fixed submission:
// #include <bits/stdc++.h>

#include <algorithm>
#include <complex>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <stack>
#include <string>
#include <unordered_map>
#include <vector>

#define INF 100000000000
#define rep(i, a) for (int i = 0; i < (a); i++)
using namespace std;

struct UnionFind {
  vector<long long int> par; // par[i] : iの親の番号
  vector<long long int> rnk; // root[i] : iの木のランク

  // コンストラクタ
  UnionFind(long long int n) : par(n), rnk(n) {
    // 木の初期化
    for (long long int i = 0; i < n; i++) {
      par[i] = i;
      rnk[i] = 1;
    }
  }

  // データxが属する木の根を再帰で取得
  long long int root(long long int x) {
    if (par[x] == x) {
      return x;
    } else {
      return par[x] = root(par[x]);
    }
  }

  // xとyが同じ木に属しているかを判定
  bool same(long long int x, long long int y) { return root(x) == root(y); }

  // xとyの木を併合
  void unite(long long int x, long long int y) {
    long long int rx = root(x); // xの根
    long long int ry = root(y); // yの根
    if (rx == ry)
      return; // 根が同じならそのまま

    if (rnk[rx] < rnk[ry]) {
      par[rx] = ry;
    } else {
      par[ry] = rx;
      if (rnk[rx] == rnk[ry])
        rnk[rx]++;
    }
  }
};

int main() {
  int n, k, l;
  cin >> n >> k >> l;

  UnionFind road(n), rail(n);
  int i;
  int p, q;
  for (i = 0; i < k; i++) {
    cin >> p >> q;
    road.unite(p - 1, q - 1);
  }
  for (i = 0; i < l; i++) {
    cin >> p >> q;
    rail.unite(p - 1, q - 1);
  }

  map<pair<int, int>, int> m;
  for (i = 0; i < n; i++) {
    m[make_pair(road.root(i), rail.root(i))]++;
  }

  for (i = 0; i < n; i++) {
    cout << m[make_pair(road.root(i), rail.root(i))] << endl;
  }
}