Problem p03575 (C++)

Buggy submission (status: Runtime Error):
#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
#define DEBUG

class UnionFind {
private:
  vector<int> par;  // 親
  vector<int> rank; // 木の深さ
  int size_;

public:
  // n要素で初期化
  UnionFind(int n) {
    par = vector<int>(n);
    rank = vector<int>(n);
    for (int i = 0; i < n; i++) {
      par[i] = i;
      rank[i] = 0;
    }
    size_ = n;
  }

  // 木の根を求める
  int find(int x) {
    if (par[x] == x) {
      return x;
    } else {
      return par[x] = find(par[x]);
    }
  }

  // xとyの属する集合を併合
  void unite(int x, int y) {
    x = find(x);
    y = find(y);
    if (x == y)
      return;
    if (rank[x] < rank[y]) {
      par[x] = y;
    } else {
      par[y] = x;
      if (rank[x] == rank[y])
        rank[x]++;
    }
    size_--;
  }

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

  int size() { return size_; }
};

void solve(long long N, long long M, std::vector<long long> a,
           std::vector<long long> b) {
  // 0-originにする
  for (int i = 0; i < N; i++) {
    a[i]--;
    b[i]--;
  }

  int cnt = 0;
  for (int i = 0; i < M; i++) {
    // i橋を落とす
    UnionFind uf(N);
    // i橋をのぞいて橋をかける
    for (int j = 0; j < M; j++) {
      if (j == i) {
        continue;
      }
      uf.unite(a[j], b[j]);
    }
    // 連結成分をかぞえる
    if (uf.size() > 1) {
      cnt++;
    }
  }

  cout << cnt << endl;
}

// Generated by 1.1.6 https://github.com/kyuridenamida/atcoder-tools  (tips: You
// use the default template now. You can remove this line by using your custom
// template)
int main() {
  long long N;
  scanf("%lld", &N);
  long long M;
  scanf("%lld", &M);
  std::vector<long long> a(M);
  std::vector<long long> b(M);
  for (int i = 0; i < M; i++) {
    scanf("%lld", &a[i]);
    scanf("%lld", &b[i]);
  }
  solve(N, M, std::move(a), std::move(b));
  return 0;
}


Fixed submission:
#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
#define DEBUG

class UnionFind {
private:
  vector<int> par;  // 親
  vector<int> rank; // 木の深さ
  int size_;

public:
  // n要素で初期化
  UnionFind(int n) {
    par = vector<int>(n);
    rank = vector<int>(n);
    for (int i = 0; i < n; i++) {
      par[i] = i;
      rank[i] = 0;
    }
    size_ = n;
  }

  // 木の根を求める
  int find(int x) {
    if (par[x] == x) {
      return x;
    } else {
      return par[x] = find(par[x]);
    }
  }

  // xとyの属する集合を併合
  void unite(int x, int y) {
    x = find(x);
    y = find(y);
    if (x == y)
      return;
    if (rank[x] < rank[y]) {
      par[x] = y;
    } else {
      par[y] = x;
      if (rank[x] == rank[y])
        rank[x]++;
    }
    size_--;
  }

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

  int size() { return size_; }
};

void solve(long long N, long long M, std::vector<long long> a,
           std::vector<long long> b) {
  // 0-originにする
  for (int i = 0; i < M; i++) {
    a[i]--;
    b[i]--;
  }

  int cnt = 0;
  for (int i = 0; i < M; i++) {
    // i橋を落とす
    UnionFind uf(N);
    // i橋をのぞいて橋をかける
    for (int j = 0; j < M; j++) {
      if (j == i) {
        continue;
      }
      uf.unite(a[j], b[j]);
    }
    // 連結成分をかぞえる
    if (uf.size() > 1) {
      cnt++;
    }
  }

  cout << cnt << endl;
}

// Generated by 1.1.6 https://github.com/kyuridenamida/atcoder-tools  (tips: You
// use the default template now. You can remove this line by using your custom
// template)
int main() {
  long long N;
  scanf("%lld", &N);
  long long M;
  scanf("%lld", &M);
  std::vector<long long> a(M);
  std::vector<long long> b(M);
  for (int i = 0; i < M; i++) {
    scanf("%lld", &a[i]);
    scanf("%lld", &b[i]);
  }
  solve(N, M, std::move(a), std::move(b));
  return 0;
}