Problem p03855 (C++)

Buggy submission (status: Runtime Error):
#include <bits/stdc++.h>
#define div1 1000000007
const long long INF = 1LL << 60;
using namespace std;
using ll = long long;
using ld = long double;
// a>b -> a==b;
template <class T> inline bool chmin(T &a, T b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}
// a<b -> a==b;
template <class T> inline bool chmax(T &a, T b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}

struct UnionFind {
  vector<ll> par;  // par[i]:iの親の番号  (例) par[3] = 2 : 3の親が2
  vector<ll> rank; // 木の深さ

  UnionFind(ll N) : par(N), rank(N) { // 最初は全てが根であるとして初期化
    for (ll i = 0; i < N; i++) {
      par[i] = i;
      rank[i] = 0;
    }
  }

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

  void unite(ll x, ll y) { // xとyの木を併合
    x = root(x);
    y = root(y);
    if (x == y)
      return; // xとyの根が同じ(=同じ木にある)時はそのまま

    if (rank[x] < rank[y]) {
      par[x] = y;
    } else {
      par[y] = x;
      if (rank[x] == rank[y])
        rank[x]++;
    }
  }

  bool same(ll x, ll y) { // 2つのデータx, yが属する木が同じならtrueを返す
    ll rx = root(x);
    ll ry = root(y);
    return rx == ry;
  }
};

int main(void) {
  ll N, K, L, i, p[100001], q[100001], r[100001], s[100001];

  cin >> N >> K >> L;

  UnionFind road(N), rail(N);

  map<pair<ll, ll>, ll> mp;

  for (i = 1; i <= K; i++) {
    cin >> p[i] >> q[i];
    road.unite(p[i], q[i]);
  }

  for (i = 1; i <= L; i++) {
    cin >> r[i] >> s[i];
    rail.unite(r[i], s[i]);
  }

  for (i = 1; i <= N; i++) {
    mp[{road.root(i), rail.root(i)}]++;
  }

  for (i = 1; i <= N; i++) {
    cout << mp[{road.root(i), rail.root(i)}] << " ";
  }
  cout << endl;

  return 0;
}

Fixed submission:
#include <bits/stdc++.h>
#define div1 1000000007
const long long INF = 1LL << 60;
using namespace std;
using ll = long long;
using ld = long double;
// a>b -> a==b;
template <class T> inline bool chmin(T &a, T b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}
// a<b -> a==b;
template <class T> inline bool chmax(T &a, T b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}

struct UnionFind {
  vector<ll> par;  // par[i]:iの親の番号  (例) par[3] = 2 : 3の親が2
  vector<ll> rank; // 木の深さ

  UnionFind(ll N) : par(N), rank(N) { // 最初は全てが根であるとして初期化
    for (ll i = 0; i < N; i++) {
      par[i] = i;
      rank[i] = 0;
    }
  }

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

  void unite(ll x, ll y) { // xとyの木を併合
    x = root(x);
    y = root(y);
    if (x == y)
      return; // xとyの根が同じ(=同じ木にある)時はそのまま

    if (rank[x] < rank[y]) {
      par[x] = y;
    } else {
      par[y] = x;
      if (rank[x] == rank[y])
        rank[x]++;
    }
  }

  bool same(ll x, ll y) { // 2つのデータx, yが属する木が同じならtrueを返す
    ll rx = root(x);
    ll ry = root(y);
    return rx == ry;
  }
};

int main(void) {
  ll N, K, L, i, p[100001], q[100001], r[100001], s[100001];

  cin >> N >> K >> L;

  UnionFind road(N + 1), rail(N + 1);

  map<pair<ll, ll>, ll> mp;

  for (i = 1; i <= K; i++) {
    cin >> p[i] >> q[i];
    road.unite(p[i], q[i]);
  }

  for (i = 1; i <= L; i++) {
    cin >> r[i] >> s[i];
    rail.unite(r[i], s[i]);
  }

  for (i = 1; i <= N; i++) {
    mp[{road.root(i), rail.root(i)}]++;
  }

  for (i = 1; i <= N; i++) {
    cout << mp[{road.root(i), rail.root(i)}] << " ";
  }
  cout << endl;

  return 0;
}