Problem p03770 (C++)

Buggy submission (status: Runtime Error):
#include <algorithm>
#include <cassert>
#include <iostream>
#include <vector>
using namespace std;
#pragma warning(disable : 4996)

long long fact[200009], mod = 1000000007, n, c[200009], w[200009], A, B;
vector<pair<long long, long long>> X;
vector<int> x[200009];
long long col[200009], cnt, num[200009];
vector<int> Z, u[200009];

long long modpow(long long a, long long b, long long m) {
  long long p = 1, q = a;
  for (int i = 0; i < 35; i++) {
    if ((b & (1LL << i)) != 0) {
      p *= q;
      p %= m;
    }
    q *= q;
    q %= m;
  }
  return p;
}
long long Div(long long a, long long b, long long m) {
  return (a * modpow(b, m - 2, m)) % m;
}
void dfs(int pos) {
  if (col[pos] >= 1)
    return;
  col[pos] = cnt;
  Z.push_back(c[pos]);
  num[c[pos]]++;
  for (int i = 0; i < x[pos].size(); i++)
    dfs(x[pos][i]);
}

void edges() {
  long long P = c[0], PP = 1000000;
  for (int i = 1; i < n; i++) {
    if (c[i] != P && w[0] + w[i] <= B) {
      if (PP == 1000000)
        PP = i;
      x[0].push_back(i);
      x[i].push_back(0);
    }
  }
  for (int i = 0; i < n; i++) {
    if (c[i] != c[PP] && w[PP] + w[i] <= B) {
      x[PP].push_back(i);
      x[i].push_back(PP);
    }
  }
  for (int i = 0; i < n; i++)
    u[c[i]].push_back(i);
  for (int i = 0; i <= n; i++) {
    for (int j = 1; j < (int)u[i].size(); j++) {
      if (w[u[i][j]] + w[u[i][0]] > A)
        continue;
      x[u[i][j]].push_back(u[i][0]);
      x[u[i][0]].push_back(u[i][j]);
    }
  }
}

int main() {
  fact[0] = 1;
  for (int i = 1; i <= 200008; i++)
    fact[i] = (1LL * fact[i - 1] * i) % mod;
  cin >> n >> A >> B;
  for (int i = 0; i < n; i++) {
    scanf("%lld%lld", &c[i], &w[i]);
    X.push_back(make_pair(w[i], c[i]));
  }
  sort(X.begin(), X.end());
  for (int i = 0; i < n; i++) {
    c[i] = X[i].second;
    w[i] = X[i].first;
  }

  edges();

  long long ans = 1;
  for (int i = 0; i < n; i++) {
    if (col[i] >= 1)
      continue;
    for (int j = 0; j < Z.size(); j++)
      num[Z[j]] = 0;
    Z.clear();
    cnt++;
    dfs(i);
    long long ret = fact[Z.size()];
    sort(Z.begin(), Z.end());
    for (int j = 0; j < Z.size(); j++) {
      if (j == 0 || Z[j - 1] != Z[j])
        ret = Div(ret, fact[num[Z[j]]], mod);
    }
    ans *= ret;
    ans %= mod;
  }
  cout << ans << endl;
  return 0;
}

Fixed submission:
#include <algorithm>
#include <cassert>
#include <iostream>
#include <vector>
using namespace std;
#pragma warning(disable : 4996)

long long fact[200009], mod = 1000000007, n, c[200009], w[200009], A, B;
vector<pair<long long, long long>> X;
vector<int> x[200009];
long long col[200009], cnt, num[200009];
vector<int> Z, u[200009];

long long modpow(long long a, long long b, long long m) {
  long long p = 1, q = a;
  for (int i = 0; i < 35; i++) {
    if ((b & (1LL << i)) != 0) {
      p *= q;
      p %= m;
    }
    q *= q;
    q %= m;
  }
  return p;
}
long long Div(long long a, long long b, long long m) {
  return (a * modpow(b, m - 2, m)) % m;
}
void dfs(int pos) {
  if (col[pos] >= 1)
    return;
  col[pos] = cnt;
  Z.push_back(c[pos]);
  num[c[pos]]++;
  for (int i = 0; i < x[pos].size(); i++)
    dfs(x[pos][i]);
}

void edges() {
  long long P = c[0], PP = 1000000;
  for (int i = 1; i < n; i++) {
    if (c[i] != P && w[0] + w[i] <= B) {
      if (PP == 1000000)
        PP = i;
      x[0].push_back(i);
      x[i].push_back(0);
    }
  }
  if (PP <= n) {
    for (int i = 0; i < n; i++) {
      if (c[i] != c[PP] && w[PP] + w[i] <= B) {
        x[PP].push_back(i);
        x[i].push_back(PP);
      }
    }
  }
  for (int i = 0; i < n; i++)
    u[c[i]].push_back(i);
  for (int i = 0; i <= n; i++) {
    for (int j = 1; j < (int)u[i].size(); j++) {
      if (w[u[i][j]] + w[u[i][0]] > A)
        continue;
      x[u[i][j]].push_back(u[i][0]);
      x[u[i][0]].push_back(u[i][j]);
    }
  }
}

int main() {
  fact[0] = 1;
  for (int i = 1; i <= 200008; i++)
    fact[i] = (1LL * fact[i - 1] * i) % mod;
  cin >> n >> A >> B;
  for (int i = 0; i < n; i++) {
    scanf("%lld%lld", &c[i], &w[i]);
    X.push_back(make_pair(w[i], c[i]));
  }
  sort(X.begin(), X.end());
  for (int i = 0; i < n; i++) {
    c[i] = X[i].second;
    w[i] = X[i].first;
  }

  edges();

  long long ans = 1;
  for (int i = 0; i < n; i++) {
    if (col[i] >= 1)
      continue;
    for (int j = 0; j < Z.size(); j++)
      num[Z[j]] = 0;
    Z.clear();
    cnt++;
    dfs(i);
    long long ret = fact[Z.size()];
    sort(Z.begin(), Z.end());
    for (int j = 0; j < Z.size(); j++) {
      if (j == 0 || Z[j - 1] != Z[j])
        ret = Div(ret, fact[num[Z[j]]], mod);
    }
    ans *= ret;
    ans %= mod;
  }
  cout << ans << endl;
  return 0;
}