Problem p02728 (C++)

Buggy submission (status: Runtime Error):
#include <bits/stdc++.h>

int main() {
  using namespace std;
  constexpr unsigned long MOD = 1000000007;
  const auto &modinv = [](unsigned long a,
                          unsigned long b = 1) -> unsigned long {
    unsigned long r{b % MOD}, n{MOD - 2};
    while (n) {
      if (n & 1)
        (r *= a) %= MOD;
      (a *= a) %= MOD;
      n >>= 1;
    }
    return r;
  };
  unsigned long N;
  cin >> N;
  vector<unsigned long> fac(N + 1, 1), invfac(N + 1, 1);
  for (unsigned long i{1}; i <= N; ++i)
    fac[i] = fac[i - 1] * i % MOD;
  invfac.back() = modinv(fac.back());
  for (unsigned long i{N}; i--;)
    invfac[i] = invfac[i + 1] * (i + 1) % MOD;
  vector<vector<unsigned long>> edge(N);
  vector<unsigned long> jisu(N);
  for (unsigned long i{1}, a, b; i < N; ++i) {
    cin >> a >> b;
    edge[--a].push_back(--b);
    edge[b].push_back(a);
    ++jisu[a];
    ++jisu[b];
  }
  assert(N < 10 || *max_element(jisu.begin(), jisu.end()) > 2);
  vector<unsigned long> ord(N);
  iota(ord.begin(), ord.end(), 0UL);
  sort(ord.begin(), ord.end(),
       [&jisu](auto i, auto j) { return jisu[i] > jisu[j]; });
  map<pair<unsigned long, unsigned long>, pair<unsigned long, unsigned long>>
      memo;
  const auto &tree_dp =
      [&modinv, &fac, &invfac, &edge,
       &memo](auto f, unsigned long now,
              unsigned long prev) -> pair<unsigned long, unsigned long> {
    if (memo.count({now, prev}))
      return memo[{now, prev}];
    if (memo.count({now, now})) {
      auto t = memo[{now, now}], s = memo[{prev, now}];
      unsigned long cnt{t.first}, ans{t.second};
      (ans *= modinv(s.second, invfac[cnt - 1] * fac[cnt - s.first - 1] % MOD *
                                   fac[s.first])) %= MOD;
      cnt -= s.first;
      return memo[{now, prev}] = {cnt, ans};
    }
    unsigned long cnt{0}, ans{1};
    for (const auto &i : edge[now])
      if (i != prev) {
        auto t = f(f, i, now);
        cnt += t.first;
        (ans *= invfac[t.first] * t.second % MOD) %= MOD;
      }
    (ans *= fac[cnt]) %= MOD;
    return memo[{now, prev}] = {cnt + 1, ans};
  };
  vector<unsigned long> ans(N);
  for (const auto &i : ord)
    ans[i] = tree_dp(tree_dp, i, i).second;
  copy(ans.begin(), ans.end(), ostream_iterator<unsigned long>(cout, "\n"));
  return 0;
}


Fixed submission:
#include <bits/stdc++.h>

int main() {
  using namespace std;
  constexpr unsigned long MOD = 1000000007;
  const auto &modinv = [](unsigned long a,
                          unsigned long b = 1) -> unsigned long {
    unsigned long r{b % MOD}, n{MOD - 2};
    while (n) {
      if (n & 1)
        (r *= a) %= MOD;
      (a *= a) %= MOD;
      n >>= 1;
    }
    return r;
  };
  unsigned long N;
  cin >> N;
  vector<unsigned long> fac(N + 1, 1), invfac(N + 1, 1);
  for (unsigned long i{1}; i <= N; ++i)
    fac[i] = fac[i - 1] * i % MOD;
  invfac.back() = modinv(fac.back());
  for (unsigned long i{N}; i--;)
    invfac[i] = invfac[i + 1] * (i + 1) % MOD;
  vector<vector<unsigned long>> edge(N);
  vector<unsigned long> jisu(N);
  for (unsigned long i{1}, a, b; i < N; ++i) {
    cin >> a >> b;
    edge[--a].push_back(--b);
    edge[b].push_back(a);
    ++jisu[a];
    ++jisu[b];
  }
  assert(N < 50000 || *max_element(jisu.begin(), jisu.end()) > 2);
  vector<unsigned long> ord(N);
  iota(ord.begin(), ord.end(), 0UL);
  sort(ord.begin(), ord.end(),
       [&jisu](auto i, auto j) { return jisu[i] > jisu[j]; });
  map<pair<unsigned long, unsigned long>, pair<unsigned long, unsigned long>>
      memo;
  const auto &tree_dp =
      [&modinv, &fac, &invfac, &edge,
       &memo](auto f, unsigned long now,
              unsigned long prev) -> pair<unsigned long, unsigned long> {
    if (memo.count({now, prev}))
      return memo[{now, prev}];
    if (memo.count({now, now})) {
      auto t = memo[{now, now}], s = memo[{prev, now}];
      unsigned long cnt{t.first}, ans{t.second};
      (ans *= modinv(s.second, invfac[cnt - 1] * fac[cnt - s.first - 1] % MOD *
                                   fac[s.first])) %= MOD;
      cnt -= s.first;
      return memo[{now, prev}] = {cnt, ans};
    }
    unsigned long cnt{0}, ans{1};
    for (const auto &i : edge[now])
      if (i != prev) {
        auto t = f(f, i, now);
        cnt += t.first;
        (ans *= invfac[t.first] * t.second % MOD) %= MOD;
      }
    (ans *= fac[cnt]) %= MOD;
    return memo[{now, prev}] = {cnt + 1, ans};
  };
  vector<unsigned long> ans(N);
  for (const auto &i : ord)
    ans[i] = tree_dp(tree_dp, i, i).second;
  copy(ans.begin(), ans.end(), ostream_iterator<unsigned long>(cout, "\n"));
  return 0;
}