Problem p02573 (C++) — buggy submission, verdict: Time Limit Exceeded

#include <bits/stdc++.h>

#define rep(i, n) for (int i = 0; i < (int)(n); i++)
#define all(v) v.begin(), v.end()
#define SP << " "
#define LLi long long int

using namespace std;

void PV(vector<int> pvv) {
  rep(i, pvv.size()) cout << pvv[i] SP;
  cout << endl;
}

void PVL(vector<LLi> pvv) {
  rep(i, pvv.size()) cout << pvv[i] SP;
  cout << endl;
}

bool VV(vector<int> vv1, vector<int> vv2) {
  if (vv1.size() != vv2.size())
    return false;
  rep(i, vv1.size()) if (vv1[i] != vv2[i]) return false;

  return true;
}

bool VVL(vector<LLi> vv1, vector<LLi> vv2) {
  if (vv1.size() != vv2.size())
    return false;
  rep(i, vv1.size()) if (vv1[i] != vv2[i]) return false;

  return true;
}

// vecotr<LLi>の総和
LLi SML(vector<LLi> smv) {
  LLi tmp = 0;
  rep(i, smv.size()) tmp += smv[i];

  return tmp;
}

struct UnionFind {
  vector<int> par; // par[i]:iの親の番号　(例) par[3] = 2 : 3の親が2
  vector<int> siz; // siz[i]:iの属する木に含まれる点の数

  UnionFind(int N) : par(N) { // 最初は全てが根であるとして初期化
    for (int i = 0; i < N; i++)
      par[i] = i;
    siz.resize(par.size(), 1); // 最初は全てサイズ1
  }

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

  int tsize(int x) { // siz[x]の木の根を見に行き、サイズを返す
    if (par[x] == x)
      return siz[x];
    par[x] = root(par[x]);
    return tsize(par[x]);
  }

  void unite(int x, int y) { // xとyの木を併合
    int rx = root(x);        // xの根をrx
    int ry = root(y);        // yの根をry
    if (rx == ry)
      return; // xとyの根が同じ(=同じ木にある)時はそのまま
    par[rx] =
        ry; // xとyの根が同じでない(=同じ木にない)時：xの根rxをyの根ryにつける
    siz[rx] += siz[ry]; // 根で管理
    siz[ry] = siz[rx];  // 根で管理
  }

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

int main() {

  int n, m, a, b, ma = 0;
  cin >> n >> m;

  UnionFind uf(n);
  rep(i, m) {
    cin >> a >> b;
    uf.unite(a - 1, b - 1);
  }

  rep(i, n) ma = max(ma, uf.tsize(i));

  cout << ma << endl;

  return 0;
}

Error: TLE

Fixed submission:

#include <bits/stdc++.h>

#define rep(i, n) for (int i = 0; i < (int)(n); i++)
#define all(v) v.begin(), v.end()
#define SP << " "
#define LLi long long int

using namespace std;

void PV(vector<int> pvv) {
  rep(i, pvv.size()) cout << pvv[i] SP;
  cout << endl;
}

void PVL(vector<LLi> pvv) {
  rep(i, pvv.size()) cout << pvv[i] SP;
  cout << endl;
}

bool VV(vector<int> vv1, vector<int> vv2) {
  if (vv1.size() != vv2.size())
    return false;
  rep(i, vv1.size()) if (vv1[i] != vv2[i]) return false;

  return true;
}

bool VVL(vector<LLi> vv1, vector<LLi> vv2) {
  if (vv1.size() != vv2.size())
    return false;
  rep(i, vv1.size()) if (vv1[i] != vv2[i]) return false;

  return true;
}

// vecotr<LLi>の総和
LLi SML(vector<LLi> smv) {
  LLi tmp = 0;
  rep(i, smv.size()) tmp += smv[i];

  return tmp;
}

struct UnionFind {
  vector<int> par; // par[i]:iの親の番号　(例) par[3] = 2 : 3の親が2
  vector<int> siz; // siz[i]:iの属する木に含まれる点の数

  UnionFind(int N) : par(N) { // 最初は全てが根であるとして初期化
    for (int i = 0; i < N; i++)
      par[i] = i;
    siz.resize(par.size(), 1); // 最初は全てサイズ1
  }

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

  int tsize(int x) { // siz[x]の木の根を見に行き、サイズを返す
    if (par[x] == x)
      return siz[x];
    return tsize(par[x]);
  }

  void unite(int x, int y) { // xとyの木を併合
    int rx = root(x);        // xの根をrx
    int ry = root(y);        // yの根をry
    if (rx == ry)
      return; // xとyの根が同じ(=同じ木にある)時はそのまま
    par[rx] =
        ry; // xとyの根が同じでない(=同じ木にない)時：xの根rxをyの根ryにつける
    siz[rx] += siz[ry]; // 根で管理
    siz[ry] = siz[rx];  // 根で管理
  }

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

int main() {

  int n, m, a, b, ma = 0;
  cin >> n >> m;

  UnionFind uf(n);
  rep(i, m) {
    cin >> a >> b;
    uf.unite(a - 1, b - 1);
  }

  rep(i, n) ma = max(ma, uf.tsize(i));

  cout << ma << endl;

  return 0;
}