Problem p02762 (C++)

Buggy submission (status: Time Limit Exceeded):
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

void dfs(int group_num, int now, vector<vector<int>> fr, vector<int> &group) {
  /*深さ有線探索
  group_num:見る頂点のグループ番号
  now:見る頂点の頂点番号
  fr:友人関係のグラフの隣接リスト表現
  group:頂点のグループ番号を格納した配列
  */
  group.at(now) = group_num;
  for (auto p : fr.at(now)) {
    // nowと友人関係にある頂点を探索
    if (group.at(p) == -1) {
      // まだグループ分けされていない
      dfs(group_num, p, fr, group);
    }
  }
  return;
}

int main() {
  int n, m, k;
  cin >> n >> m >> k;
  /*
  fr:友人関係のグラフの隣接リスト表現
  fr_num:それぞれの人の友人の数
  bl:ブロック関係をまとめた配列
  */
  vector<vector<int>> fr(n);
  vector<int> fr_num(n, 0);
  vector<pair<int, int>> bl(k);
  for (int i = 0; i < m; i++) {
    int a, b;
    cin >> a >> b;
    a--;
    b--;
    fr.at(a).push_back(b);
    fr.at(b).push_back(a);
    fr_num.at(a)++;
    fr_num.at(b)++;
  }
  for (int i = 0; i < k; i++) {
    int c, d;
    cin >> c >> d;
    c--;
    d--;
    pair<int, int> p;
    p.first = c;
    p.second = d;
    bl.at(i) = p;
  }
  // group: 各頂点のグループ番号を格納する配列。-1で初期化
  vector<int> group(n, -1);
  for (int i = 0; i < n; i++) {
    if (group.at(i) == -1) {
      dfs(i, i, fr, group);
    }
  }
  // group_num:各グループにいくつの頂点が含まれているか
  vector<int> group_num(n, 0);
  for (int i = 0; i < n; i++) {
    group_num.at(group.at(i))++;
  }
  // ans:答えを格納する配列
  vector<int> ans(n);
  for (int i = 0; i < n; i++) {
    // 自分のグループの要素数　-　すでに友達の人数　- 自分
    ans.at(i) = group_num.at(group.at(i)) - fr_num.at(i) - 1;
  }

  for (int i = 0; i < k; i++) {
    int c, d;
    // ブロック関係にあるけど同じグループの人を引く。
    c = bl.at(i).first;
    d = bl.at(i).second;
    if (group.at(c) == group.at(d)) {
      ans.at(c)--;
      ans.at(d)--;
    }
  }
  for (int i = 0; i < n; i++) {
    cout << ans.at(i) << ' ';
  }
}


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

void dfs(int group_num, int now, vector<vector<int>> &fr, vector<int> &group) {
  /*深さ有線探索
  group_num:見る頂点のグループ番号
  now:見る頂点の頂点番号
  fr:友人関係のグラフの隣接リスト表現
  group:頂点のグループ番号を格納した配列
  */
  group.at(now) = group_num;
  for (auto p : fr.at(now)) {
    // nowと友人関係にある頂点を探索
    if (group.at(p) == -1) {
      // まだグループ分けされていない
      dfs(group_num, p, fr, group);
    }
  }
  return;
}

int main() {
  int n, m, k;
  cin >> n >> m >> k;
  /*
  fr:友人関係のグラフの隣接リスト表現
  fr_num:それぞれの人の友人の数
  bl:ブロック関係をまとめた配列
  */
  vector<vector<int>> fr(n);
  vector<int> fr_num(n, 0);
  vector<pair<int, int>> bl(k);
  for (int i = 0; i < m; i++) {
    int a, b;
    cin >> a >> b;
    a--;
    b--;
    fr.at(a).push_back(b);
    fr.at(b).push_back(a);
    fr_num.at(a)++;
    fr_num.at(b)++;
  }
  for (int i = 0; i < k; i++) {
    int c, d;
    cin >> c >> d;
    c--;
    d--;
    pair<int, int> p;
    p.first = c;
    p.second = d;
    bl.at(i) = p;
  }
  // group: 各頂点のグループ番号を格納する配列。-1で初期化
  vector<int> group(n, -1);
  for (int i = 0; i < n; i++) {
    if (group.at(i) == -1) {
      dfs(i, i, fr, group);
    }
  }
  // group_num:各グループにいくつの頂点が含まれているか
  vector<int> group_num(n, 0);
  for (int i = 0; i < n; i++) {
    group_num.at(group.at(i))++;
  }
  // ans:答えを格納する配列
  vector<int> ans(n);
  for (int i = 0; i < n; i++) {
    // 自分のグループの要素数　-　すでに友達の人数　- 自分
    ans.at(i) = group_num.at(group.at(i)) - fr_num.at(i) - 1;
  }

  for (int i = 0; i < k; i++) {
    int c, d;
    // ブロック関係にあるけど同じグループの人を引く。
    c = bl.at(i).first;
    d = bl.at(i).second;
    if (group.at(c) == group.at(d)) {
      ans.at(c)--;
      ans.at(d)--;
    }
  }
  for (int i = 0; i < n; i++) {
    cout << ans.at(i) << ' ';
  }
}