Problem p00884 (C++) — buggy submission, verdict: Runtime Error

#include <algorithm>
#include <iostream>
#include <unordered_map>
#include <vector>

int N;
std::unordered_map<std::string, int> dict;
std::string name[100];
std::vector<std::string> groups[100];
std::vector<int> graph[100];
bool visited[100];

template <int n> class UnionFind {
public:
  UnionFind() {
    for (int i = 0; i < n; i++) {
      par[i] = i;
      rank[i] = 0;
    }
  }
  int find(int x) {
    if (x == par[x])
      return x;
    return par[x] = find(par[x]);
  }
  bool same(int x, int y) { return find(x) == find(y); }
  void unite(int x, int y) {
    x = find(x);
    y = find(y);
    if (x == y) {
      return;
    }

    if (rank[x] > rank[y]) {
      par[y] = x;
    } else {
      par[x] = y;
      if (rank[x] == rank[y]) {
        rank[y]++;
      }
    }
  }
  int rank[n], par[n];
};

UnionFind<100> uf;

void dfs(int u) {
  visited[u] = true;
  for (int v : graph[u]) {
    if (visited[v]) {
      continue;
    }

    uf.unite(u, v);
    // printf("%d -> %d\\n", u, v);
    dfs(v);
  }
}

int main() {
  while (std::cin >> N, N) {
    dict.clear();
    for (int i = 0; i < 100; i++) {
      groups[i].clear();
      graph[i].clear();
      visited[i] = false;
    }
    uf = UnionFind<100>();

    for (int i = 0; i < N; i++) {
      std::string S;
      std::cin >> S;

      int pos = S.find(":");
      name[i] = S.substr(0, pos);
      dict[name[i]] = i;

      int prev = pos + 1;
      while ((pos = S.find(",", pos)) != std::string::npos) {
        groups[i].push_back(S.substr(prev, pos - prev));
        prev = pos + 1;
        pos += 1;
      }

      groups[i].push_back(S.substr(prev, S.size() - prev - 1));
    }

    for (int i = 0; i < N; i++) {
      for (const auto &member : groups[i]) {
        if (dict.count(member) > 0) {
          graph[i].push_back(dict[member]);
        }
      }
    }

    dfs(0);

    // for(int i=0;i<N;i++){
    //     std::cout << "(" << i << ")" << std::endl;
    //     std::cout << name[i];
    //     std::cout << ": ";
    //     for(auto &member : groups[i]){
    //         std::cout << member << " ";
    //     }
    //     std::cout << std::endl;
    // }

    std::vector<std::string> members;

    for (int i = 0; i < N; i++) {
      if (!uf.same(0, i)) {
        continue;
      }

      for (auto &member : groups[i]) {
        if (dict.count(member) > 0) {
          continue;
        }
        members.push_back(member);
      }
    }

    std::sort(members.begin(), members.end());
    members.erase(std::unique(members.begin(), members.end()), members.end());

    // for(auto& s : members){
    //     std::cout << s << std::endl;
    // }

    std::cout << members.size() << std::endl;
  }
}

Error: 0

Fixed submission:

#include <algorithm>
#include <iostream>
#include <unordered_map>
#include <vector>

int N;
std::unordered_map<std::string, int> dict;
std::string name[100];
std::vector<std::string> groups[100];
std::vector<int> graph[100];
int order[100];
bool visited[100];

void dfs(int u, int &k) {
  visited[u] = true;

  for (int v : graph[u]) {
    if (!visited[v]) {
      dfs(v, k);
    }
  }

  order[k++] = u;
}

void topological() {
  std::fill(visited, visited + 100, false);

  int k = 0;
  for (int i = 0; i < N; i++) {
    if (!visited[i]) {
      dfs(i, k);
    }
  }
}

int main() {
  while (std::cin >> N, N) {
    dict.clear();
    for (int i = 0; i < 100; i++) {
      groups[i].clear();
      graph[i].clear();
    }

    for (int i = 0; i < N; i++) {
      std::string S;
      std::cin >> S;

      int pos = S.find(":");
      name[i] = S.substr(0, pos);
      dict[name[i]] = i;

      int prev = pos + 1;
      while ((pos = S.find(",", pos)) != std::string::npos) {
        groups[i].push_back(S.substr(prev, pos - prev));
        prev = pos + 1;
        pos += 1;
      }

      groups[i].push_back(S.substr(prev, S.size() - prev - 1));

      // std::cout << name[i] << std::endl;
      // for(auto& s : groups[i]){
      //     std::cout << s << std::endl;
      // }
      // std::cout << std::string(40, '-') << std::endl;
    }

    for (int i = 0; i < N; i++) {
      for (const auto &member : groups[i]) {
        if (dict.count(member) > 0) {
          graph[dict[member]].push_back(i);
        }
      }
    }

    topological();

    for (int i = N - 1; i >= 0; i--) {
      int u = order[i];
      for (auto v : graph[u]) {
        groups[v].erase(std::find(groups[v].begin(), groups[v].end(), name[u]));

        for (auto member : groups[u]) {
          groups[v].push_back(member);
        }
      }
    }

    std::sort(groups[0].begin(), groups[0].end());
    groups[0].erase(std::unique(groups[0].begin(), groups[0].end()),
                    groups[0].end());

    std::cout << groups[0].size() << std::endl;
  }
}