Problem p03052 (C++)

Buggy submission (status: Runtime Error):
/* cerberus97 - Hanit Banga */

#include <algorithm>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <vector>

using namespace std;

#define pb push_back
#define fast_cin()                                                             \
  ios_base::sync_with_stdio(false);                                            \
  cin.tie(NULL)

typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;

const int N = 25, M = 200, S = (1 << 19) + 5;
const int mod = 1e9 + 7;

vector<pii> g[N];
int u[N], v[N], depth[N], par[N], up[N];
int dep[M];
int ctr[S];
ll ways[S], sum[S];
ll prod[M][M];

void dfs(int u, int p);

int main() {
  // cout << (2 * sizeof(ways)) / 1e6 << endl;
  // return 0;
  fast_cin();
  int n, m;
  cin >> n >> m;
  for (int i = 0; i < m; ++i) {
    cin >> u[i] >> v[i];
    if (i < n - 1) {
      g[u[i]].pb({v[i], i});
      g[v[i]].pb({u[i], i});
    }
  }
  dfs(1, 0);
  for (int i = n - 1; i < m; ++i) {
    int eu = u[i], ev = v[i];
    if (depth[eu] < depth[ev]) {
      swap(eu, ev);
    }
    while (depth[eu] > depth[ev]) {
      dep[i] |= (1 << up[eu]);
      eu = par[eu];
    }
    while (eu != ev) {
      dep[i] |= (1 << up[eu]);
      dep[i] |= (1 << up[ev]);
      eu = par[eu];
      ev = par[ev];
    }
  }
  for (int i = 1; i < M; ++i) {
    prod[i][i - 1] = 1;
    for (int j = i; j < M; ++j) {
      prod[i][j] = prod[i][j - 1] * j;
      prod[i][j] %= mod;
    }
  }
  int subsets = (1 << (n - 1));
  for (int mask = 0; mask < subsets; ++mask) {
    // ctr[mask] = __builtin_popcount(mask);
    for (int i = n - 1; i < m; ++i) {
      if (dep[i] & mask) {
        ++ctr[mask];
      }
    }
  }
  ways[0] = 1;
  for (int mask = 0; mask < subsets; ++mask) {
    // cout << mask << ' ' << ways[mask] << ' ' << sum[mask] << ' ' << ctr[mask]
    // << endl;
    int b = __builtin_popcount(mask), tot = ctr[mask] + b;
    for (int i = 0; i < n - 1; ++i) {
      if (mask & (1 << i)) {
        continue;
      }
      int new_mask = mask | (1 << i);
      int k = ctr[new_mask] - ctr[mask];
      ll temp = prod[tot + 1][tot + k] * ways[mask];
      temp %= mod;
      ways[new_mask] += temp;
      ways[new_mask] %= mod;
      sum[new_mask] += prod[tot + 2][tot + k + 1] * sum[mask];
      sum[new_mask] += temp * (b + 1);
      sum[new_mask] %= mod;
    }
  }
  cout << sum[subsets - 1] << endl;
}

void dfs(int u, int p) {
  for (auto &e : g[u]) {
    int v = e.first, id = e.second;
    if (v != p) {
      depth[v] = depth[u] + 1;
      par[v] = u;
      up[v] = id;
      dfs(v, u);
    }
  }
}

Fixed submission:
/* cerberus97 - Hanit Banga */

#include <algorithm>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <vector>

using namespace std;

#define pb push_back
#define fast_cin()                                                             \
  ios_base::sync_with_stdio(false);                                            \
  cin.tie(NULL)

typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;

const int N = 25, M = 200, S = (1 << 19) + 5;
const int mod = 1e9 + 7;

vector<pii> g[N];
int u[M], v[M], depth[N], par[N], up[N];
int dep[M];
int ctr[S];
ll ways[S], sum[S];
ll prod[M][M];

void dfs(int u, int p);

int main() {
  // cout << (2 * sizeof(ways)) / 1e6 << endl;
  // return 0;
  fast_cin();
  int n, m;
  cin >> n >> m;
  for (int i = 0; i < m; ++i) {
    cin >> u[i] >> v[i];
    if (i < n - 1) {
      g[u[i]].pb({v[i], i});
      g[v[i]].pb({u[i], i});
    }
  }
  dfs(1, 0);
  for (int i = n - 1; i < m; ++i) {
    int eu = u[i], ev = v[i];
    if (depth[eu] < depth[ev]) {
      swap(eu, ev);
    }
    while (depth[eu] > depth[ev]) {
      dep[i] |= (1 << up[eu]);
      eu = par[eu];
    }
    while (eu != ev) {
      dep[i] |= (1 << up[eu]);
      dep[i] |= (1 << up[ev]);
      eu = par[eu];
      ev = par[ev];
    }
  }
  for (int i = 1; i < M; ++i) {
    prod[i][i - 1] = 1;
    for (int j = i; j < M; ++j) {
      prod[i][j] = prod[i][j - 1] * j;
      prod[i][j] %= mod;
    }
  }
  int subsets = (1 << (n - 1));
  for (int mask = 0; mask < subsets; ++mask) {
    // ctr[mask] = __builtin_popcount(mask);
    for (int i = n - 1; i < m; ++i) {
      if (dep[i] & mask) {
        ++ctr[mask];
      }
    }
  }
  ways[0] = 1;
  for (int mask = 0; mask < subsets; ++mask) {
    // cout << mask << ' ' << ways[mask] << ' ' << sum[mask] << ' ' << ctr[mask]
    // << endl;
    int b = __builtin_popcount(mask), tot = ctr[mask] + b;
    for (int i = 0; i < n - 1; ++i) {
      if (mask & (1 << i)) {
        continue;
      }
      int new_mask = mask | (1 << i);
      int k = ctr[new_mask] - ctr[mask];
      ll temp = prod[tot + 1][tot + k] * ways[mask];
      temp %= mod;
      ways[new_mask] += temp;
      ways[new_mask] %= mod;
      sum[new_mask] += prod[tot + 2][tot + k + 1] * sum[mask];
      sum[new_mask] += temp * (b + 1);
      sum[new_mask] %= mod;
    }
  }
  cout << sum[subsets - 1] << endl;
}

void dfs(int u, int p) {
  for (auto &e : g[u]) {
    int v = e.first, id = e.second;
    if (v != p) {
      depth[v] = depth[u] + 1;
      par[v] = u;
      up[v] = id;
      dfs(v, u);
    }
  }
}