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

#include <algorithm>
#include <bitset>
#include <cassert>
#include <chrono>
#include <cmath>
#include <complex>
#include <deque>
#include <functional>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <limits>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <tuple>
#include <vector>
using namespace std;

typedef long long ll;
typedef uint64_t ull;
typedef pair<int, int> P;
typedef pair<int, double> Pid;
typedef pair<double, int> Pdi;
typedef pair<ll, int> Pl;
typedef pair<ll, ll> Pll;
typedef pair<int, pair<int, int>> PP;
typedef pair<P, int> PPi;
constexpr double PI = 3.1415926535897932; // acos(-1)
constexpr double EPS = 1e-9;
constexpr int INF = 1001001001;
constexpr int mod = 1000000007;
// constexpr int mod = 998244353;

#define chmax(x, y) x = max(x, y)
#define chmin(x, y) x = min(x, y)
#define chadd(x, y) x = (x + y) % mod

template <int mod> struct ModInt {
  int x;

  ModInt() : x(0) {}

  ModInt(int64_t y) : x(y >= 0 ? y % mod : (mod - (-y) % mod) % mod) {}

  ModInt &operator+=(const ModInt &p) {
    if ((x += p.x) >= mod)
      x -= mod;
    return *this;
  }

  ModInt &operator-=(const ModInt &p) {
    if ((x += mod - p.x) >= mod)
      x -= mod;
    return *this;
  }

  ModInt &operator*=(const ModInt &p) {
    x = (int)(1LL * x * p.x % mod);
    return *this;
  }

  ModInt &operator/=(const ModInt &p) {
    *this *= p.inverse();
    return *this;
  }

  ModInt operator-() const { return ModInt(-x); }

  ModInt operator+(const ModInt &p) const { return ModInt(*this) += p; }

  ModInt operator-(const ModInt &p) const { return ModInt(*this) -= p; }

  ModInt operator*(const ModInt &p) const { return ModInt(*this) *= p; }

  ModInt operator/(const ModInt &p) const { return ModInt(*this) /= p; }

  bool operator==(const ModInt &p) const { return x == p.x; }

  bool operator!=(const ModInt &p) const { return x != p.x; }

  ModInt inverse() const {
    int a = x, b = mod, u = 1, v = 0, t;
    while (b > 0) {
      t = a / b;
      swap(a -= t * b, b);
      swap(u -= t * v, v);
    }
    return ModInt(u);
  }

  ModInt pow(int64_t n) const {
    ModInt ret(1), mul(x);
    while (n > 0) {
      if (n & 1)
        ret *= mul;
      mul *= mul;
      n >>= 1;
    }
    return ret;
  }

  friend ostream &operator<<(ostream &os, const ModInt &p) { return os << p.x; }

  friend istream &operator>>(istream &is, ModInt &a) {
    int64_t t;
    is >> t;
    a = ModInt<mod>(t);
    return (is);
  }

  static int get_mod() { return mod; }
};

using modint = ModInt<mod>;

template <typename T> struct Combination {
  int sz;
  vector<T> fact_;
  vector<T> ifact_;
  vector<T> inv_;

  Combination(int n = 1e+6) : sz(n) {
    fact_.resize(sz + 1);
    ifact_.resize(sz + 1);
    inv_.resize(sz + 1);

    fact_[0] = ifact_[sz] = inv_[0] = 1;
    for (int i = 1; i <= sz; ++i)
      fact_[i] = fact_[i - 1] * i;
    ifact_[sz] /= fact_[sz];
    for (int i = sz; i > 0; --i)
      ifact_[i - 1] = ifact_[i] * i;
    for (int i = 1; i <= sz; ++i)
      inv_[i] = ifact_[i] * fact_[i - 1];
  }

  inline T fact(int k) const { return fact_[k]; }
  inline T ifact(int k) const { return ifact_[k]; }
  inline T inv(int k) const { return inv_[k]; }

  T get_permutation(int n, int k) {
    if (n < 0 || k < 0 || n < k)
      return 0;
    return fact(n) * ifact(n - k);
  }

  T get_combination(int n, int k) {
    if (n < 0 || k < 0 || n < k)
      return 0;
    return fact(n) * ifact(k) * ifact(n - k);
  }
};

int n;
vector<vector<int>> graph;
vector<int> partial(200005, 0);    // 部分木サイズ
vector<modint> dp(200005, -1);     // 頂点0 を根としたときの木DP
vector<modint> product(200005, 1); // 累積積
vector<modint> dp2(200005, -1);    // 全方位木DP
Combination<modint> c(200005);

int calc_size(int from = 0, int p = -1) {
  int res = 1;
  for (int to : graph[from]) {
    if (to == p)
      continue;
    res += calc_size(to, from);
  }
  return partial[from] = res;
}

modint dfs(int from = 0, int p = -1) {
  if (dp[from] != -1)
    return dp[from];
  modint res = c.fact(partial[from] - 1);
  for (int to : graph[from]) {
    if (to == p)
      continue;
    res *= c.ifact(partial[to]);
    res *= dfs(to, from);
    product[from] *= dfs(to, from);
  }
  return dp[from] = res;
}

void dfs2(int from = 0, int p = -1) {
  if (p == -1) {
    dp2[from] = dp[from];
    for (int to : graph[from])
      dfs2(to, from);
    return;
  }

  dp2[from] = dp2[p];
  dp2[from] *= c.fact(partial[from]) * dp[from].inverse();
  dp2[from] *= c.fact(n - partial[from] - 1) * c.ifact(n - partial[from]);
  for (int to : graph[from]) {
    if (to == p)
      continue;
    dp2[from] *= dp[to];
    dp2[from] *= c.ifact(partial[to]);
  }
  for (int to : graph[from]) {
    if (to == p)
      continue;
    dfs2(to, from);
  }
  return;
}

int main() {
  ios::sync_with_stdio(false);
  cin.tie(nullptr);

  cin >> n;
  graph.resize(n);
  for (int i = 0; i < n - 1; ++i) {
    int a, b;
    cin >> a >> b;
    --a, --b;
    graph[a].push_back(b);
    graph[b].push_back(a);
  }

  calc_size();
  dfs();
  dfs2();
  for (int i = 0; i < n; ++i)
    cout << dp2[i] << "\\n";
}

Error: WA

Fixed submission:

#include <algorithm>
#include <bitset>
#include <cassert>
#include <chrono>
#include <cmath>
#include <complex>
#include <deque>
#include <functional>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <limits>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <tuple>
#include <vector>
using namespace std;

typedef long long ll;
typedef uint64_t ull;
typedef pair<int, int> P;
typedef pair<int, double> Pid;
typedef pair<double, int> Pdi;
typedef pair<ll, int> Pl;
typedef pair<ll, ll> Pll;
typedef pair<int, pair<int, int>> PP;
typedef pair<P, int> PPi;
constexpr double PI = 3.1415926535897932; // acos(-1)
constexpr double EPS = 1e-9;
constexpr int INF = 1001001001;
constexpr int mod = 1000000007;
// constexpr int mod = 998244353;

#define chmax(x, y) x = max(x, y)
#define chmin(x, y) x = min(x, y)
#define chadd(x, y) x = (x + y) % mod

template <int mod> struct ModInt {
  int x;

  ModInt() : x(0) {}

  ModInt(int64_t y) : x(y >= 0 ? y % mod : (mod - (-y) % mod) % mod) {}

  ModInt &operator+=(const ModInt &p) {
    if ((x += p.x) >= mod)
      x -= mod;
    return *this;
  }

  ModInt &operator-=(const ModInt &p) {
    if ((x += mod - p.x) >= mod)
      x -= mod;
    return *this;
  }

  ModInt &operator*=(const ModInt &p) {
    x = (int)(1LL * x * p.x % mod);
    return *this;
  }

  ModInt &operator/=(const ModInt &p) {
    *this *= p.inverse();
    return *this;
  }

  ModInt operator-() const { return ModInt(-x); }

  ModInt operator+(const ModInt &p) const { return ModInt(*this) += p; }

  ModInt operator-(const ModInt &p) const { return ModInt(*this) -= p; }

  ModInt operator*(const ModInt &p) const { return ModInt(*this) *= p; }

  ModInt operator/(const ModInt &p) const { return ModInt(*this) /= p; }

  bool operator==(const ModInt &p) const { return x == p.x; }

  bool operator!=(const ModInt &p) const { return x != p.x; }

  ModInt inverse() const {
    int a = x, b = mod, u = 1, v = 0, t;
    while (b > 0) {
      t = a / b;
      swap(a -= t * b, b);
      swap(u -= t * v, v);
    }
    return ModInt(u);
  }

  ModInt pow(int64_t n) const {
    ModInt ret(1), mul(x);
    while (n > 0) {
      if (n & 1)
        ret *= mul;
      mul *= mul;
      n >>= 1;
    }
    return ret;
  }

  friend ostream &operator<<(ostream &os, const ModInt &p) { return os << p.x; }

  friend istream &operator>>(istream &is, ModInt &a) {
    int64_t t;
    is >> t;
    a = ModInt<mod>(t);
    return (is);
  }

  static int get_mod() { return mod; }
};

using modint = ModInt<mod>;

template <typename T> struct Combination {
  int sz;
  vector<T> fact_;
  vector<T> ifact_;
  vector<T> inv_;

  Combination(int n = 1e+6) : sz(n) {
    fact_.resize(sz + 1);
    ifact_.resize(sz + 1);
    inv_.resize(sz + 1);

    fact_[0] = ifact_[sz] = inv_[0] = 1;
    for (int i = 1; i <= sz; ++i)
      fact_[i] = fact_[i - 1] * i;
    ifact_[sz] /= fact_[sz];
    for (int i = sz; i > 0; --i)
      ifact_[i - 1] = ifact_[i] * i;
    for (int i = 1; i <= sz; ++i)
      inv_[i] = ifact_[i] * fact_[i - 1];
  }

  inline T fact(int k) const { return fact_[k]; }
  inline T ifact(int k) const { return ifact_[k]; }
  inline T inv(int k) const { return inv_[k]; }

  T get_permutation(int n, int k) {
    if (n < 0 || k < 0 || n < k)
      return 0;
    return fact(n) * ifact(n - k);
  }

  T get_combination(int n, int k) {
    if (n < 0 || k < 0 || n < k)
      return 0;
    return fact(n) * ifact(k) * ifact(n - k);
  }
};

int n;
vector<vector<int>> graph;
vector<int> partial(100005, 0);    // 部分木サイズ
vector<modint> dp(100005, -1);     // 頂点0 を根としたときの木DP
vector<modint> product(100005, 1); // 累積積
vector<modint> dp2(100005, -1);    // 全方位木DP
Combination<modint> c;

int calc_size(int from = 0, int p = -1) {
  int res = 1;
  for (int to : graph[from]) {
    if (to == p)
      continue;
    res += calc_size(to, from);
  }
  return partial[from] = res;
}

modint dfs(int from = 0, int p = -1) {
  if (dp[from] != -1)
    return dp[from];
  modint res = c.fact(partial[from] - 1);
  for (int to : graph[from]) {
    if (to == p)
      continue;
    res *= c.ifact(partial[to]);
    res *= dfs(to, from);
    product[from] *= dfs(to, from);
  }
  return dp[from] = res;
}

void dfs2(int from = 0, int p = -1) {
  if (p == -1) {
    dp2[from] = dp[from];
    for (int to : graph[from])
      dfs2(to, from);
    return;
  }

  dp2[from] = dp2[p];
  dp2[from] *= c.fact(partial[from]) * dp[from].inverse();
  dp2[from] *= c.fact(n - partial[from] - 1) * c.ifact(n - partial[from]);
  for (int to : graph[from]) {
    if (to == p)
      continue;
    dp2[from] *= dp[to];
    dp2[from] *= c.ifact(partial[to]);
  }
  for (int to : graph[from]) {
    if (to == p)
      continue;
    dfs2(to, from);
  }
  return;
}

int main() {
  ios::sync_with_stdio(false);
  cin.tie(nullptr);

  cin >> n;
  graph.resize(n);
  for (int i = 0; i < n - 1; ++i) {
    int a, b;
    cin >> a >> b;
    --a, --b;
    graph[a].push_back(b);
    graph[b].push_back(a);
  }

  calc_size();
  dfs();
  dfs2();
  for (int i = 0; i < n; ++i)
    cerr << dp2[i] << "\\n";
}