Problem p03354 (C++)

Buggy submission (status: Runtime Error):
#include <bits/stdc++.h>
using namespace std;
#define REP(i, N) for (i = 0; i < N; i++)
#define MAX_I INT_MAX      // 1e9
#define MIN_I INT_MIN      //-1e9
#define MAX_UI UINT_MAX    // 1e9
#define MAX_LL LLONG_MAX   // 1e18
#define MIN_LL LLONG_MIN   //-1e18
#define MAX_ULL ULLONG_MAX // 1e19
typedef long long ll;
typedef pair<int, int> PII;
typedef pair<char, char> PCC;
typedef pair<ll, ll> PLL;
typedef pair<char, int> PCI;
typedef pair<int, char> PIC;
typedef pair<ll, int> PLI;
typedef pair<int, ll> PIL;
typedef pair<ll, char> PLC;
typedef pair<char, ll> PCL;

class UnionFind {
public:
  // 親の番号を格納．親の場合は-(その集合のサイズ)
  vector<int> Parent;
  // 作るときはParentの値をすべて-1にする
  UnionFind(int N) { Parent = vector<int>(N, -1); }

  // 親を求める
  int find(int x) {
    if (Parent[x] < 0)
      return x;
    // 親の紐づけを変更
    return Parent[x] = find(Parent[x]);
  }

  // xの属する集合のサイズを取ってくる
  int size(int x) { return -Parent[find(x)]; }

  // xとyの属する集合を併合
  // 併合できたらtrue，すでに併合していたらfalse
  bool unite(int x, int y) {
    // xとyを直接つけない，親同士をつける
    x = find(x);
    y = find(y);
    if (x == y)
      return false;

    // 大きいほうに小さいほうをくっつける
    if (size(x) < size(y))
      swap(x, y);

    // xのサイズを更新
    Parent[x] += Parent[y];
    Parent[y] = x;
    return true;
  }

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

int main(void) {
  int N, M;
  cin >> N >> M;
  vector<int> p(N + 1);
  UnionFind uni = UnionFind(N + 1);
  int i, j;
  int count = 0;
  REP(i, N + 1) {
    if (i == 0)
      p[i] = 0;
    cin >> p[i];
    if (p[i] == i)
      count++;
  }
  REP(j, M) {
    int x, y;
    cin >> x >> y;
    uni.unite(x, y);
  }
  REP(i, N + 1) {
    if (i == 0)
      continue;
    if (i != p[i] && uni.same(i, p[i]))
      count++;
  }
  cout << count << endl;
  return 0;
}


Fixed submission:
#include <bits/stdc++.h>
using namespace std;
#define REP(i, N) for (i = 0; i < N; i++)
#define MAX_I INT_MAX      // 1e9
#define MIN_I INT_MIN      //-1e9
#define MAX_UI UINT_MAX    // 1e9
#define MAX_LL LLONG_MAX   // 1e18
#define MIN_LL LLONG_MIN   //-1e18
#define MAX_ULL ULLONG_MAX // 1e19
typedef long long ll;
typedef pair<int, int> PII;
typedef pair<char, char> PCC;
typedef pair<ll, ll> PLL;
typedef pair<char, int> PCI;
typedef pair<int, char> PIC;
typedef pair<ll, int> PLI;
typedef pair<int, ll> PIL;
typedef pair<ll, char> PLC;
typedef pair<char, ll> PCL;

class UnionFind {
public:
  // 親の番号を格納．親の場合は-(その集合のサイズ)
  vector<int> Parent;
  // 作るときはParentの値をすべて-1にする
  UnionFind(int N) { Parent = vector<int>(N, -1); }

  // 親を求める
  int find(int x) {
    if (Parent[x] < 0)
      return x;
    // 親の紐づけを変更
    return Parent[x] = find(Parent[x]);
  }

  // xの属する集合のサイズを取ってくる
  int size(int x) { return -Parent[find(x)]; }

  // xとyの属する集合を併合
  // 併合できたらtrue，すでに併合していたらfalse
  bool unite(int x, int y) {
    // xとyを直接つけない，親同士をつける
    x = find(x);
    y = find(y);
    if (x == y)
      return false;

    // 大きいほうに小さいほうをくっつける
    if (size(x) < size(y))
      swap(x, y);

    // xのサイズを更新
    Parent[x] += Parent[y];
    Parent[y] = x;
    return true;
  }

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

int main(void) {
  int N, M;
  cin >> N >> M;
  vector<int> p(N + 1);
  UnionFind uni = UnionFind(N + 1);
  int i, j;
  int count = 0;
  REP(i, N + 1) {
    if (i == 0)
      continue;
    cin >> p[i];
    if (p[i] == i)
      count++;
  }
  REP(j, M) {
    int x, y;
    cin >> x >> y;
    uni.unite(x, y);
  }
  REP(i, N + 1) {
    if (i == 0)
      continue;
    if (i != p[i] && uni.same(i, p[i]))
      count++;
  }
  cout << count << endl;
  return 0;
}