Problem p02728 (C++) — buggy submission, verdict: Time Limit Exceeded

// -----------------------------------
// Author     : MatsuTaku
// Affiliation: Tokushima University
// Country    : Japan
// Date       : 03/29/2020
// -----------------------------------

#include <bits/stdc++.h>

using namespace std;
using ll = long long;

template <typename T, T MOD> class modint {
private:
  T val_;

public:
  constexpr modint() : val_(0) {}
  constexpr modint(T v) : val_(v % MOD) {}
  constexpr modint &operator=(T v) {
    val_ = v % MOD;
    return *this;
  }

  constexpr T val() const { return val_; }
  constexpr modint operator+(modint x) const { return (val() + x.val()) % MOD; }
  constexpr modint operator+=(modint x) { return *this = *this + x; }
  constexpr modint operator++() { return *this += 1; }
  constexpr modint operator++(int) {
    modint c = *this;
    ++(*this);
    return c;
  }
  constexpr modint operator-(modint x) const {
    return (val() + MOD - x.val()) % MOD;
  }
  constexpr modint operator-=(modint x) { return *this = *this - x; }
  constexpr modint operator--() { return *this -= 1; }
  constexpr modint operator--(int) {
    modint c = *this;
    --(*this);
    return c;
  }
  constexpr modint operator*(modint x) const { return (val() * x.val()) % MOD; }
  constexpr modint operator*=(modint x) { return *this = *this * x; }
  friend constexpr modint pow(modint x, T p) {
    modint t = 1;
    modint u = x;
    while (p) {
      if (p & 1)
        t *= u;
      u *= u;
      p >>= 1;
    }
    return t;
  }
  constexpr modint operator/(modint x) const {
    return *this * pow(modint{x}, MOD - 2);
  }
  constexpr modint operator/=(modint x) { return *this = *this / x; }

  constexpr bool operator==(modint x) const { return val() == x.val(); }
  constexpr bool operator!=(modint x) const { return val() != x.val(); }
  constexpr bool operator<(modint x) const { return val() < x.val(); };
  constexpr bool operator<=(modint x) const { return val() <= x.val(); };
  constexpr bool operator>(modint x) const { return val() > x.val(); };
  constexpr bool operator>=(modint x) const { return val() >= x.val(); };

  friend std::ostream &operator<<(std::ostream &os, modint x) {
    return os << x.val();
  }
  friend std::istream &operator>>(std::istream &is, modint &x) {
    return is >> x.val_;
  }
};

using mint = modint<unsigned long long, (unsigned long long)1e9 + 7>;

constexpr size_t MAX = 2e5;

vector<mint> fact(MAX + 1), ifact(MAX + 1);
void init() {
  fact[0] = 1;
  for (ll i = 1; i <= MAX; i++)
    fact[i] = fact[i - 1] * i;
  ifact[MAX] = mint{1} / fact[MAX];
  for (ll i = MAX - 1; i >= 0; i--)
    ifact[i] = ifact[i + 1] * (i + 1);
}

mint combination(int a, int b) { return fact[a] * ifact[a - b] * ifact[b]; }

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

  init();

  int N;
  cin >> N;
  vector<vector<int>> graph(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);
  }

  struct Monoid {
    int size;
    mint pat;
    Monoid(int size = 1, mint pat = 1) : size(size), pat(pat) {}
    Monoid merge(const Monoid &a) const {
      auto x = *this;
      x.size += a.size;
      x.pat *= a.pat * combination(x.size - 1, a.size);
      return x;
    }
    Monoid erase(const Monoid &a) const {
      auto x = *this;
      x.pat /= a.pat * combination(x.size - 1, a.size);
      x.size -= a.size;
      return x;
    }
  };

  vector<Monoid> dp(N);
  auto dfs = [&](auto dfs, int c, int p = -1) -> void {
    for (auto t : graph[c]) {
      if (t == p)
        continue;
      dfs(dfs, t, c);
      dp[c] = dp[c].merge(dp[t]);
    }
  };
  dfs(dfs, 0);
  auto bfs = [&](auto bfs, int c, int p = -1) -> void {
    for (auto t : graph[c]) {
      if (t == p)
        continue;
      dp[t] = dp[t].merge(dp[c].erase(dp[t]));
      bfs(bfs, t, c);
    }
  };
  bfs(bfs, 0);

  for (int i = 0; i < N; i++) {
    cout << dp[i].pat << endl;
  }

  return 0;
}


Error: TLE

Fixed submission:

// -----------------------------------
// Author     : MatsuTaku
// Affiliation: Tokushima University
// Country    : Japan
// Date       : 03/29/2020
// -----------------------------------

#include <bits/stdc++.h>

using namespace std;
using ll = long long;

template <typename T, T MOD> class modint {
private:
  T val_;

public:
  constexpr modint() : val_(0) {}
  constexpr modint(T v) : val_(v % MOD) {}
  constexpr modint &operator=(T v) {
    val_ = v % MOD;
    return *this;
  }

  constexpr T val() const { return val_; }
  constexpr modint operator+(modint x) const { return (val() + x.val()) % MOD; }
  constexpr modint operator+=(modint x) { return *this = *this + x; }
  constexpr modint operator++() { return *this += 1; }
  constexpr modint operator++(int) {
    modint c = *this;
    ++(*this);
    return c;
  }
  constexpr modint operator-(modint x) const {
    return (val() + MOD - x.val()) % MOD;
  }
  constexpr modint operator-=(modint x) { return *this = *this - x; }
  constexpr modint operator--() { return *this -= 1; }
  constexpr modint operator--(int) {
    modint c = *this;
    --(*this);
    return c;
  }
  constexpr modint operator*(modint x) const { return (val() * x.val()) % MOD; }
  constexpr modint operator*=(modint x) { return *this = *this * x; }
  friend constexpr modint pow(modint x, T p) {
    modint t = 1;
    modint u = x;
    while (p) {
      if (p & 1)
        t *= u;
      u *= u;
      p >>= 1;
    }
    return t;
  }
  constexpr modint operator/(modint x) const {
    return *this * pow(modint{x}, MOD - 2);
  }
  constexpr modint operator/=(modint x) { return *this = *this / x; }

  constexpr bool operator==(modint x) const { return val() == x.val(); }
  constexpr bool operator!=(modint x) const { return val() != x.val(); }
  constexpr bool operator<(modint x) const { return val() < x.val(); };
  constexpr bool operator<=(modint x) const { return val() <= x.val(); };
  constexpr bool operator>(modint x) const { return val() > x.val(); };
  constexpr bool operator>=(modint x) const { return val() >= x.val(); };

  friend std::ostream &operator<<(std::ostream &os, modint x) {
    return os << x.val();
  }
  friend std::istream &operator>>(std::istream &is, modint &x) {
    return is >> x.val_;
  }
};

using mint = modint<unsigned long long, (unsigned long long)1e9 + 7>;

constexpr size_t MAX = 2e5;

vector<mint> fact(MAX + 1), ifact(MAX + 1);
void init() {
  fact[0] = 1;
  for (ll i = 1; i <= MAX; i++)
    fact[i] = fact[i - 1] * i;
  ifact[MAX] = mint{1} / fact[MAX];
  for (ll i = MAX - 1; i >= 0; i--)
    ifact[i] = ifact[i + 1] * (i + 1);
}

int dfs_size(const vector<vector<int>> &graph, vector<map<int, int>> &size,
             int par, int c) {
  if (size[c].count(par))
    return size[c][par];
  int res = 1;
  for (auto t : graph[c]) {
    if (t == par)
      continue;
    res += dfs_size(graph, size, c, t);
  }
  return size[c][par] = res;
}

mint dfs(const vector<vector<int>> &graph, vector<map<int, int>> &size,
         vector<map<int, mint>> &dp, int par, int c) {
  if (dp[c].count(par))
    return dp[c][par];
  mint res = fact[dfs_size(graph, size, par, c) - 1];
  for (auto t : graph[c]) {
    if (t == par)
      continue;
    res *= dfs(graph, size, dp, c, t) * ifact[dfs_size(graph, size, c, t)];
  }
  return dp[c][par] = res;
}

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

  init();

  int N;
  cin >> N;
  vector<vector<int>> graph(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);
  }

  vector<map<int, int>> size(N);
  vector<map<int, mint>> dp(N);
  for (int i = 0; i < N; i++) {
    cout << dfs(graph, size, dp, -1, i) << endl;
  }

  return 0;
}