Problem p02762 (C++)

Buggy submission (status: Runtime Error):
#include <algorithm>
#include <cmath>
#include <deque>
#include <iomanip>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <utility>
#include <vector>
using namespace std;
using ll = long long;
#define rep(i, n) for (int i = 0; i < n; i++)
#define repk(i, k, n) for (int i = k; i < n; i++)
#define MOD 1e9 + 7
#define INF 1e9
#define PIE 3.14159265358979323

template <class T> inline bool chmin(T &a, T b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}
template <class T> inline bool chmax(T &a, T b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}
template <class T> T GCD(T a, T b) {
  if (b == 0)
    return a;
  else
    return GCD(b, a % b);
}
template <class T> inline T LCM(T a, T b) { return (a * b) / GCD(a, b); }

template <class T> struct Union_find {
  /*
T: integer(int, long longなど)
n個の整数に対してunion find森を生成
par: 親の配列 ex)par[x]はxの親
rank: ランクの配列で、root以外は意味はない
size_of: サイズの配列で、root以外は意味がない
root(x): xの根を返す
same(x, y): boolでxとyが連結かを返す
size(x): xが含まれる木の要素数を返す
unite(x, y): xが含まれる木とyが含まれる木を連結させる
*/
  vector<int> par;
  vector<int> rank;
  vector<int> size_of;

  Union_find(T n) : par(n), rank(n) {
    for (int i = 0; i < n; i++) {
      par[i] = i;
      rank[i] = 0;
      size_of[i] = 1;
    }
  }

  int root(T x) { return par[x] == x ? x : par[x] = root(par[x]); }

  bool same(T x, T y) { return root(x) == root(y); }

  int size(T x) { return size_of[root(x)]; }

  void unite(T x, T y) {
    x = root(x);
    y = root(y);
    if (x == y) {
      return;
    }
    if (rank[x] < rank[y]) {
      size_of[y] += size_of[x];
      par[x] = y;
    } else {
      size_of[x] += size_of[y];
      par[y] = x;
      if (rank[x] == rank[y])
        rank[x]++;
    }
    return;
  }
};

int main() {
  int n, m, k;
  cin >> n >> m >> k;
  vector<set<int>> cannot_make_friends_with(n);
  int a, b;
  Union_find<int> uf(n);
  rep(i, m) {
    cin >> a >> b;
    a--;
    b--;
    uf.unite(a, b);
    cannot_make_friends_with[a].insert(b);
    cannot_make_friends_with[b].insert(a);
  }
  int c, d;
  rep(i, k) {
    cin >> c >> d;
    c--;
    d--;
    if (uf.same(c, d)) {
      cannot_make_friends_with[c].insert(d);
      cannot_make_friends_with[d].insert(c);
    }
  }
  rep(i, n) {
    cout << uf.size(i) - cannot_make_friends_with[i].size() - 1;
    if (i != n - 1)
      cout << " ";
    else
      cout << endl;
  }
  return 0;
}

Fixed submission:
#include <algorithm>
#include <cmath>
#include <deque>
#include <iomanip>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <utility>
#include <vector>
using namespace std;
using ll = long long;
#define rep(i, n) for (int i = 0; i < n; i++)
#define repk(i, k, n) for (int i = k; i < n; i++)
#define MOD 1e9 + 7
#define INF 1e9
#define PIE 3.14159265358979323

template <class T> inline bool chmin(T &a, T b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}
template <class T> inline bool chmax(T &a, T b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}
template <class T> T GCD(T a, T b) {
  if (b == 0)
    return a;
  else
    return GCD(b, a % b);
}
template <class T> inline T LCM(T a, T b) { return (a * b) / GCD(a, b); }

template <class T> struct Union_find {
  /*
T: integer(int, long longなど)
n個の整数に対してunion find森を生成
par: 親の配列 ex)par[x]はxの親
rank: ランクの配列で、root以外は意味はない
size_of: サイズの配列で、root以外は意味がない
root(x): xの根を返す
same(x, y): boolでxとyが連結かを返す
size(x): xが含まれる木の要素数を返す
unite(x, y): xが含まれる木とyが含まれる木を連結させる
*/
  vector<int> par;
  vector<int> rank;
  vector<int> size_of;

  Union_find(T n) : par(n), rank(n) {
    for (int i = 0; i < n; i++) {
      par[i] = i;
      rank[i] = 0;
      size_of.push_back(1);
    }
  }

  int root(T x) { return par[x] == x ? x : par[x] = root(par[x]); }

  bool same(T x, T y) { return root(x) == root(y); }

  int size(T x) { return size_of[root(x)]; }

  void unite(T x, T y) {
    x = root(x);
    y = root(y);
    if (x == y) {
      return;
    }
    if (rank[x] < rank[y]) {
      size_of[y] += size_of[x];
      par[x] = y;
    } else {
      size_of[x] += size_of[y];
      par[y] = x;
      if (rank[x] == rank[y])
        rank[x]++;
    }
    return;
  }
};

int main() {
  int n, m, k;
  cin >> n >> m >> k;
  vector<set<int>> cannot_make_friends_with(n);
  int a, b;
  Union_find<int> uf(n);
  rep(i, m) {
    cin >> a >> b;
    a--;
    b--;
    uf.unite(a, b);
    cannot_make_friends_with[a].insert(b);
    cannot_make_friends_with[b].insert(a);
  }
  int c, d;
  rep(i, k) {
    cin >> c >> d;
    c--;
    d--;
    if (uf.same(c, d)) {
      cannot_make_friends_with[c].insert(d);
      cannot_make_friends_with[d].insert(c);
    }
  }
  rep(i, n) {
    cout << uf.size(i) - cannot_make_friends_with[i].size() - 1;
    if (i != n - 1)
      cout << " ";
    else
      cout << endl;
  }
  return 0;
}