Problem p03575 (C++)

Buggy submission (status: Runtime Error):
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <functional>
#include <iomanip>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <string>
#include <utility>
#include <vector>

using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll MOD = 1000000007;
#define rep(i, n) for (int i = 0; i < n; i++)
#define repl(i, s, e) for (int i = s; i < e; i++)
#define reple(i, s, e) for (int i = s; i <= e; i++)
#define revrep(i, n) for (int i = n - 1; i >= 0; i--)
#define all(x) (x).begin(), (x).end()

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

class UnionFind {
  // par[i]：ノードiの親
  // count[i]：iが親の時、iが属するグループのノード数
  vector<int> par;
  vector<int> count;

  int m_groupCount = 0;

public:
  UnionFind(int N) {
    m_groupCount = N;

    for (int i = 0; i < N; i++) {
      // 最初は全てが根であるとして初期化
      par.push_back(i);
      count.push_back(1);
    }
  }

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

    // ついでに親を張り替え
    return par[x] = root(par[x]);
  }

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

    // 要素数の変更
    count[ry] += count[rx];
    count[rx] = 0;

    // 木の併合によってグループが1つ減る
    m_groupCount--;
  }

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

  // 指定したデータxが属するグループの要素数を返す
  int size(int x) { return count[root(x)]; }

  // UnionFindのグループの個数を返す
  int groupCount() { return m_groupCount; }
};

int main() {
  int N, M;
  cin >> N >> M;

  vector<pair<int, int>> E(N);

  rep(i, M) {
    int a, b;
    cin >> a >> b;
    --a;
    --b;
    E[i].first = a;
    E[i].second = b;
  }

  ll count = 0;

  rep(i, M) {
    UnionFind uf(N);

    rep(j, M) {
      if (j == i)
        continue;

      uf.unite(E[j].first, E[j].second);
    }

    if (uf.groupCount() != 1)
      count++;
  }

  cout << count << endl;

  return 0;
}

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

using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll MOD = 1000000007;
#define rep(i, n) for (int i = 0; i < n; i++)
#define repl(i, s, e) for (int i = s; i < e; i++)
#define reple(i, s, e) for (int i = s; i <= e; i++)
#define revrep(i, n) for (int i = n - 1; i >= 0; i--)
#define all(x) (x).begin(), (x).end()

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

class UnionFind {
  // par[i]：ノードiの親
  // count[i]：iが親の時、iが属するグループのノード数
  vector<int> par;
  vector<int> count;

  int m_groupCount = 0;

public:
  UnionFind(int N) {
    m_groupCount = N;

    for (int i = 0; i < N; i++) {
      // 最初は全てが根であるとして初期化
      par.push_back(i);
      count.push_back(1);
    }
  }

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

    // ついでに親を張り替え
    return par[x] = root(par[x]);
  }

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

    // 要素数の変更
    count[ry] += count[rx];
    count[rx] = 0;

    // 木の併合によってグループが1つ減る
    m_groupCount--;
  }

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

  // 指定したデータxが属するグループの要素数を返す
  int size(int x) { return count[root(x)]; }

  // UnionFindのグループの個数を返す
  int groupCount() { return m_groupCount; }
};

int main() {
  int N, M;
  cin >> N >> M;

  vector<pair<int, int>> E(M);

  rep(i, M) {
    int a, b;
    cin >> a >> b;
    --a;
    --b;
    E[i].first = a;
    E[i].second = b;
  }

  ll count = 0;

  rep(i, M) {
    UnionFind uf(N);

    rep(j, M) {
      if (j == i)
        continue;

      uf.unite(E[j].first, E[j].second);
    }

    if (uf.groupCount() != 1)
      count++;
  }

  cout << count << endl;

  return 0;
}