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

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

#define int long long
typedef vector<int> vint;
typedef pair<int, int> pint;
typedef vector<pint> vpint;
#define rep(i, n) for (int i = 0; i < (n); i++)
#define reps(i, f, n) for (int i = (f); i < (n); i++)
#define all(v) (v).begin(), (v).end()
#define each(it, v)                                                            \\
  for (__typeof((v).begin()) it = (v).begin(); it != (v).end(); it++)
#define pb push_back
#define fi first
#define se second
template <typename A, typename B> inline void chmin(A &a, B b) {
  if (a > b)
    a = b;
}
template <typename A, typename B> inline void chmax(A &a, B b) {
  if (a < b)
    a = b;
}

const int mod = 1000000009;
int mpow(int n, int m) {
  n %= mod;
  int ret = 1;
  while (m) {
    if (m & 1)
      ret = ret * n % mod;
    n = n * n % mod;
    m >>= 1;
  }
  return ret;
}

int N, M;
int fact[3333333];
int inv[3333333];

int C(int n, int k) { return fact[n] * inv[k] % mod * inv[n - k] % mod; }

struct UnionFindTree {
  vector<int> par, sz;
  UnionFindTree(int n) {
    par.resize(n);
    sz.resize(n);
    for (int i = 0; i < n; i++) {
      par[i] = i;
      sz[i] = 1;
    }
  }
  int find(int x) { return x == par[x] ? x : par[x] = find(par[x]); }
  void unite(int x, int y) {
    x = find(x);
    y = find(y);
    if (x == y)
      return;
    if (sz[x] < sz[y])
      swap(x, y);
    sz[x] += sz[y];
    par[y] = x;
  }
  bool areSame(int x, int y) { return find(x) == find(y); }
  int size(int x) { return sz[find(x)]; }
};

int table[3333333];

int calc(vpint A) {
  vint xs;
  rep(i, A.size()) {
    xs.pb(A[i].fi);
    xs.pb(A[i].se);
  }
  sort(all(xs));
  xs.erase(unique(all(xs)), xs.end());
  rep(i, A.size()) {
    A[i].fi = lower_bound(all(xs), A[i].fi) - xs.begin();
    A[i].se = lower_bound(all(xs), A[i].se) - xs.begin();
  }

  UnionFindTree uf(xs.size());
  rep(i, A.size()) uf.unite(A[i].fi, A[i].se);

  int cnt = 0;
  rep(i, xs.size()) {
    if (uf.find(i) != i)
      continue;
    if (uf.sz[i] > 3)
      return 0;
    if (uf.sz[i] == 3)
      continue;
    cnt++;
  }

  int n = 3 * N - (int)xs.size();

  if (n < cnt)
    return 0;

  int ret = fact[n] * inv[n - cnt] % mod;
  ret = ret * table[n - cnt] % mod;
  return ret;
}

signed main() {
  fact[0] = 1;
  for (int i = 1; i < 3333333; i++)
    fact[i] = fact[i - 1] * i % mod;
  inv[3333333 - 1] = mpow(fact[3333333 - 1], mod - 2);
  for (int i = 3333333 - 2; i >= 0; i--)
    inv[i] = inv[i + 1] * (i + 1) % mod;
  table[0] = 1;
  for (int i = 3; i < 3333333; i += 3) {
    table[i] = table[i - 3] * C(i - 1, 2) % mod;
  }

  cin >> N >> M;

  vpint A, B;
  rep(i, M) {
    int a, b, c;
    cin >> a >> b >> c;
    if (c == 0)
      A.pb({a, b});
    else
      B.pb({a, b});
  }

  int ans = 0;

  int k = B.size();
  for (int i = 1; i < (1 << k); i++) {
    vpint AA = A;
    rep(j, k) if (i >> j & 1) AA.pb(B[j]);

    int pc = 0;
    rep(j, k) if (i >> j & 1) pc++;
    if (pc % 2 == 1)
      ans = (ans + calc(AA)) % mod;
    else
      ans = (ans - calc(AA) + mod) % mod;

    //  assert(0<=calc(AA)&&calc(AA)<mod);
  }

  cout << (calc(A) - ans + mod) % mod << endl;
  return 0;
}

Error: 0

Fixed submission:

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

#define int long long
typedef vector<int> vint;
typedef pair<int, int> pint;
typedef vector<pint> vpint;
#define rep(i, n) for (int i = 0; i < (n); i++)
#define reps(i, f, n) for (int i = (f); i < (n); i++)
#define all(v) (v).begin(), (v).end()
#define each(it, v)                                                            \\
  for (__typeof((v).begin()) it = (v).begin(); it != (v).end(); it++)
#define pb push_back
#define fi first
#define se second
template <typename A, typename B> inline void chmin(A &a, B b) {
  if (a > b)
    a = b;
}
template <typename A, typename B> inline void chmax(A &a, B b) {
  if (a < b)
    a = b;
}

const int mod = 1000000009;
int mpow(int n, int m) {
  n %= mod;
  int ret = 1;
  while (m) {
    if (m & 1)
      ret = ret * n % mod;
    n = n * n % mod;
    m >>= 1;
  }
  return ret;
}

int N, M;
int fact[3333333];
int inv[3333333];

int C(int n, int k) { return fact[n] * inv[k] % mod * inv[n - k] % mod; }

struct UnionFindTree {
  vector<int> par, sz;
  UnionFindTree(int n) {
    par.resize(n);
    sz.resize(n);
    for (int i = 0; i < n; i++) {
      par[i] = i;
      sz[i] = 1;
    }
  }
  int find(int x) { return x == par[x] ? x : par[x] = find(par[x]); }
  void unite(int x, int y) {
    x = find(x);
    y = find(y);
    if (x == y)
      return;
    if (sz[x] < sz[y])
      swap(x, y);
    sz[x] += sz[y];
    par[y] = x;
  }
  bool areSame(int x, int y) { return find(x) == find(y); }
  int size(int x) { return sz[find(x)]; }
};

int table[3333333];

int calc(vpint A) {
  vint xs;
  rep(i, A.size()) {
    xs.pb(A[i].fi);
    xs.pb(A[i].se);
  }
  sort(all(xs));
  xs.erase(unique(all(xs)), xs.end());
  rep(i, A.size()) {
    A[i].fi = lower_bound(all(xs), A[i].fi) - xs.begin();
    A[i].se = lower_bound(all(xs), A[i].se) - xs.begin();
  }

  UnionFindTree uf(xs.size());
  rep(i, A.size()) uf.unite(A[i].fi, A[i].se);

  int cnt = 0;
  rep(i, xs.size()) {
    if (uf.find(i) != i)
      continue;
    if (uf.sz[i] > 3)
      return 0;
    if (uf.sz[i] == 3)
      continue;
    cnt++;
  }

  int n = 3 * N - (int)xs.size();
  assert(0 <= n && n <= 3 * N);
  assert(n - cnt >= 0);
  // assert((n-cnt)%3==0);
  int ret = fact[n] * inv[n - cnt] % mod;
  ret = ret * table[n - cnt] % mod;
  //  assert(0<=ret&&ret<mod);
  return ret;
}

signed main() {
  fact[0] = 1;
  for (int i = 1; i < 3333333; i++)
    fact[i] = fact[i - 1] * i % mod;
  inv[3333333 - 1] = mpow(fact[3333333 - 1], mod - 2);
  for (int i = 3333333 - 2; i >= 0; i--)
    inv[i] = inv[i + 1] * (i + 1) % mod;
  table[0] = 1;
  for (int i = 3; i < 3333333; i += 3) {
    table[i] = table[i - 3] * C(i - 1, 2) % mod;
  }

  cin >> N >> M;

  vpint A, B;
  rep(i, M) {
    int a, b, c;
    cin >> a >> b >> c;
    if (c == 0)
      A.pb({a, b});
    else
      B.pb({a, b});
  }

  int ans = 0;

  int k = B.size();
  for (int i = 1; i < (1 << k); i++) {
    vpint AA = A;
    rep(j, k) if (i >> j & 1) AA.pb(B[j]);

    int pc = 0;
    rep(j, k) if (i >> j & 1) pc++;
    if (pc % 2 == 1)
      ans = (ans + calc(AA)) % mod;
    else
      ans = (ans - calc(AA) + mod) % mod;

    //  assert(0<=calc(AA)&&calc(AA)<mod);
  }

  cout << (calc(A) - ans + mod) % mod << endl;
  return 0;
}