Problem p03604 (C++)

Buggy submission (status: Runtime Error):
#include <algorithm>
#include <cctype>
#include <cstdio>
#include <cstring>
#define repu(i, x, y) for (int i = x; i <= y; ++i)
using namespace std;

typedef long long LL;
const int p = 1000000007;
int n, fac[200100], inv[200100], ans, cntv, cnte, a[200100], deg[200100],
    link[200100], s[200100];
bool flag[200100];
struct edge {
  int v;
  edge *nxt;
} pool[600100], *tp = pool, *fst[200100], *fst2[200100];

int getint() {
  char ch;
  while (!isdigit(ch = getchar()))
    ;
  int x = ch - '0';
  for (; isdigit(ch = getchar()); x = x * 10 + ch - '0')
    ;
  return x;
}

int c(int n, int m) { return LL(fac[n]) * inv[m] % p * inv[n - m] % p; }

void addedge(int u, int v, edge **fst) {
  *tp = (edge){v, fst[u]}, fst[u] = tp++;
}

void dfs1(int x) {
  flag[x] = 1, a[++cntv] = x;
  for (edge *i = fst[x]; i; i = i->nxt)
    if (flag[i->v])
      ++cnte, ++deg[x], ++deg[i->v];
  for (edge *i = fst[x]; i; i = i->nxt)
    if (!flag[i->v])
      dfs1(i->v);
}

int dfs2(int x) {
  int ret = s[x] = 1;
  for (edge *i = fst2[x]; i; i = i->nxt) {
    ret = LL(ret) * dfs2(i->v) % p;
    s[x] += s[i->v], ret = LL(ret) * c(s[x] - 1, s[i->v]) % p;
  }
  return ret;
}

int calc() {
  static bool flag[200100];
  edge *t = tp;
  repu(i, 1, cntv) flag[a[i]] = 0;
  repu(i, 1, cntv) for (edge *j = fst[a[i]]; j;
                        j = j->nxt) if (j->v < link[a[i]])
      addedge(a[i], j->v, fst2),
      flag[j->v] = 1;
  int sum = 0, ret = 1;
  repu(i, 1, cntv) if (!flag[a[i]]) {
    ret = LL(ret) * dfs2(a[i]) % p;
    ret = LL(ret) * c(sum += s[a[i]], s[a[i]]) % p;
  }
  tp = t;
  repu(i, 1, cntv) fst2[a[i]] = 0;
  return ret;
}

int solve(int x) {
  cntv = cnte = 0, dfs1(x);
  if (cntv != cnte) {
    puts("0");
    exit(0);
  }
  repu(i, 1, cntv) if (deg[a[i]] ==
                       1) for (int j = a[i], nxt = 0; j;
                               j = nxt,
                               nxt = 0) for (edge *k = fst[j]; k;
                                             k = k->nxt) if (deg[k->v] > 1) {
    link[j] = k->v;
    if (--deg[k->v] == 1)
      nxt = k->v;
  }
  static int cyc[200100], tot;
  repu(i, 1, cntv) if (deg[a[i]] > 1) {
    cyc[tot = 1] = a[i];
    while (tot == 1 || cyc[tot] != a[i])
      for (edge *j = fst[cyc[tot]]; j; j = j->nxt)
        if (deg[j->v] > 1 && cyc[tot - 1] != j->v) {
          cyc[++tot] = j->v;
          break;
        }
    --tot;
    break;
  }
  repu(i, 1, tot) link[cyc[i]] = cyc[i + 1];
  int sum = calc();
  repu(i, 1, tot) link[cyc[i + 1]] = cyc[i];
  (sum += calc()) %= p, ans = LL(ans) * sum % p;
  return cntv;
}

int main() {
  n = getint(), ans = 1;
  repu(i, 1, n * 2) {
    int u = getint(), v = getint() + n;
    addedge(u, v, fst), addedge(v, u, fst);
  }
  fac[0] = fac[1] = inv[0] = inv[1] = 1;
  repu(i, 2, n * 2) inv[i] = LL(p - p / i) * inv[p % i] % p;
  repu(i, 2, n * 2) fac[i] = LL(fac[i - 1]) * i % p,
                    inv[i] = LL(inv[i - 1]) * inv[i] % p;
  int sum = 0;
  repu(i, 1, n * 2) if (!flag[i]) {
    int cnt = solve(i);
    ans = LL(ans) * c(sum += cnt, cnt) % p;
  }
  printf("%d\n", ans);
  return 0;
}

Fixed submission:
#include <algorithm>
#include <cctype>
#include <cstdio>
#include <cstring>
#define repu(i, x, y) for (int i = x; i <= y; ++i)
using namespace std;

typedef long long LL;
const int p = 1000000007;
int n, fac[200100], inv[200100], ans, cntv, cnte, a[200100], deg[200100],
    link[200100], s[200100];
bool flag[200100];
struct edge {
  int v;
  edge *nxt;
} pool[600100], *tp = pool, *fst[200100], *fst2[200100];

int getint() {
  char ch;
  while (!isdigit(ch = getchar()))
    ;
  int x = ch - '0';
  for (; isdigit(ch = getchar()); x = x * 10 + ch - '0')
    ;
  return x;
}

int c(int n, int m) { return LL(fac[n]) * inv[m] % p * inv[n - m] % p; }

void addedge(int u, int v, edge **fst) {
  *tp = (edge){v, fst[u]}, fst[u] = tp++;
}

void dfs1(int x) {
  flag[x] = 1, a[++cntv] = x;
  for (edge *i = fst[x]; i; i = i->nxt)
    if (flag[i->v])
      ++cnte, ++deg[x], ++deg[i->v];
  for (edge *i = fst[x]; i; i = i->nxt)
    if (!flag[i->v])
      dfs1(i->v);
}

int dfs2(int x) {
  int ret = s[x] = 1;
  for (edge *i = fst2[x]; i; i = i->nxt) {
    ret = LL(ret) * dfs2(i->v) % p;
    s[x] += s[i->v], ret = LL(ret) * c(s[x] - 1, s[i->v]) % p;
  }
  return ret;
}

int calc() {
  static bool flag[200100];
  edge *t = tp;
  repu(i, 1, cntv) flag[a[i]] = 0;
  repu(i, 1, cntv) for (edge *j = fst[a[i]]; j;
                        j = j->nxt) if (j->v < link[a[i]])
      addedge(a[i], j->v, fst2),
      flag[j->v] = 1;
  int sum = 0, ret = 1;
  repu(i, 1, cntv) if (!flag[a[i]]) {
    ret = LL(ret) * dfs2(a[i]) % p;
    ret = LL(ret) * c(sum += s[a[i]], s[a[i]]) % p;
  }
  tp = t;
  repu(i, 1, cntv) fst2[a[i]] = 0;
  return ret;
}

int solve(int x) {
  cntv = cnte = 0, dfs1(x);
  if (cntv != cnte) {
    puts("0");
    exit(0);
  }
  repu(i, 1, cntv) if (deg[a[i]] ==
                       1) for (int j = a[i], nxt = 0; j;
                               deg[j] = 0, j = nxt,
                               nxt = 0) for (edge *k = fst[j]; k;
                                             k = k->nxt) if (deg[k->v] > 1) {
    link[j] = k->v;
    if (--deg[k->v] == 1)
      nxt = k->v;
  }
  static int cyc[200100], tot;
  repu(i, 1, cntv) if (deg[a[i]] > 1) {
    cyc[tot = 1] = a[i];
    while (tot == 1 || cyc[tot] != a[i])
      for (edge *j = fst[cyc[tot]]; j; j = j->nxt)
        if (deg[j->v] > 1 && cyc[tot - 1] != j->v) {
          cyc[++tot] = j->v;
          break;
        }
    --tot;
    break;
  }
  repu(i, 1, tot) link[cyc[i]] = cyc[i + 1];
  int sum = calc();
  repu(i, 1, tot) link[cyc[i + 1]] = cyc[i];
  (sum += calc()) %= p, ans = LL(ans) * sum % p;
  return cntv;
}

int main() {
  n = getint(), ans = 1;
  repu(i, 1, n * 2) {
    int u = getint(), v = getint() + n;
    addedge(u, v, fst), addedge(v, u, fst);
  }
  fac[0] = fac[1] = inv[0] = inv[1] = 1;
  repu(i, 2, n * 2) inv[i] = LL(p - p / i) * inv[p % i] % p;
  repu(i, 2, n * 2) fac[i] = LL(fac[i - 1]) * i % p,
                    inv[i] = LL(inv[i - 1]) * inv[i] % p;
  int sum = 0;
  repu(i, 1, n * 2) if (!flag[i]) {
    int cnt = solve(i);
    ans = LL(ans) * c(sum += cnt, cnt) % p;
  }
  printf("%d\n", ans);
  return 0;
}