Problem p03855 (C++)

Buggy submission (status: Time Limit Exceeded):
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <deque>
#include <functional>
#include <iomanip>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>

// #define INF 1000000000;
#define MOD 1000000007;
#define LIMIT 1000000000000000000;
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
#define int long long
#define rep(i, n) for (int i = 0; i < (int)(n); i++)
typedef pair<int, int> P;

template <class T> bool chmin(T &a, T b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}

template <class T> bool chmax(T &a, T b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}

struct Setup {
  Setup() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(20);
  }
} SETUP;

const int INF = 1LL << 60;

class UnionFindTree {
private:
  vector<int> m_parent; // 親ノードの番号を格納。-1なら自分自身が親(root)

public:
  // 頂点数で初期化。最初は全てのノードが非連結。
  UnionFindTree(int x) : m_parent(x, -1) {}

  // xがどのグループに属しているかを調べる。
  int root(int x) {
    if (m_parent[x] < 0) {
      return x;
    }
    m_parent[x] = root(m_parent[x]); // 高速化のため、親を根に繋ぎかておく。
    return m_parent[x];
  }

  // xの属するグループの頂点数を調べる。
  int size(int x) { return -m_parent[root(x)]; }

  // xが属する集合とyが属する集合を連結する。
  bool unite(int x, int y) {
    x = root(x);
    y = root(y);
    if (x == y) {
      return false; // すでにくっついているからくっつけない。
    }

    // ノード番号の大きい方(x)に小さい方(y)をくっつけたい。
    if (size(x) < size(y))
      swap(x, y);

    // xのサイズを更新。
    m_parent[x] += m_parent[y];
    // yの親をxにする。
    m_parent[y] = x;
    return true;
  }

  // 同じグループか？
  bool is_same_group(int x, int y) { return root(x) == root(y); }
};

signed main() {
  int n, k, l;
  cin >> n >> k >> l;
  UnionFindTree ufl(n), ufr(n);
  rep(i, k) {
    int a, b;
    cin >> a >> b;
    a--, b--;
    ufl.unite(a, b);
  }
  rep(i, l) {
    int a, b;
    cin >> a >> b;
    a--, b--;
    ufr.unite(a, b);
  }

  rep(i, n) {
    int ans = 0;
    rep(j, n) {
      if (ufl.is_same_group(i, j) && ufr.is_same_group(i, j)) {
        ans++;
      }
    }
    cout << ans << " ";
  }
  cout << endl;
}

Fixed submission:
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <deque>
#include <functional>
#include <iomanip>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>

// #define INF 1000000000;
#define MOD 1000000007;
#define LIMIT 1000000000000000000;
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
#define int long long
#define rep(i, n) for (int i = 0; i < (int)(n); i++)
typedef pair<int, int> P;

template <class T> bool chmin(T &a, T b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}

template <class T> bool chmax(T &a, T b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}

struct Setup {
  Setup() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(20);
  }
} SETUP;

const int INF = 1LL << 60;

class UnionFindTree {
private:
  vector<int> m_parent; // 親ノードの番号を格納。-1なら自分自身が親(root)

public:
  // 頂点数で初期化。最初は全てのノードが非連結。
  UnionFindTree(int x) : m_parent(x, -1) {}

  // xがどのグループに属しているかを調べる。
  int root(int x) {
    if (m_parent[x] < 0) {
      return x;
    }
    m_parent[x] = root(m_parent[x]); // 高速化のため、親を根に繋ぎかておく。
    return m_parent[x];
  }

  // xの属するグループの頂点数を調べる。
  int size(int x) { return -m_parent[root(x)]; }

  // xが属する集合とyが属する集合を連結する。
  bool unite(int x, int y) {
    x = root(x);
    y = root(y);
    if (x == y) {
      return false; // すでにくっついているからくっつけない。
    }

    // ノード番号の大きい方(x)に小さい方(y)をくっつけたい。
    if (size(x) < size(y))
      swap(x, y);

    // xのサイズを更新。
    m_parent[x] += m_parent[y];
    // yの親をxにする。
    m_parent[y] = x;
    return true;
  }

  // 同じグループか？
  bool is_same_group(int x, int y) { return root(x) == root(y); }
};

signed main() {
  int n, k, l;
  cin >> n >> k >> l;
  UnionFindTree ufl(n), ufr(n);
  rep(i, k) {
    int a, b;
    cin >> a >> b;
    a--, b--;
    ufl.unite(a, b);
  }
  rep(i, l) {
    int a, b;
    cin >> a >> b;
    a--, b--;
    ufr.unite(a, b);
  }

  map<P, int> mp;
  rep(i, n) { mp[P(ufl.root(i), ufr.root(i))]++; }
  rep(i, n) { cout << mp[P(ufl.root(i), ufr.root(i))] << " "; }
  cout << endl;
}