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

#include <bits/stdc++.h>
using namespace std;

using Size = int;
using Vertex = int;
using Weight = long long;
struct Edge {
  Vertex from, to;
  Weight weight;
};
using Graph = std::vector<std::vector<Edge>>;

using LL = long long;
const LL M = 1e9 + 7;

LL combination(LL n, LL r) {
  if (n < r)
    return 0;
  if (n < 0 || r < 0)
    return 0;
  static std::vector<LL> fact{1, 1}, inv{1, 1}, finv{1, 1};
  for (LL i = fact.size(); i <= n; ++i) {
    fact.emplace_back(fact.back() * i % M);
    inv.emplace_back(inv.at(M % i) * (M - M / i) % M);
    finv.emplace_back(finv.back() * inv.back() % M);
  }
  return (fact[n] * finv[n - r] % M) * finv[r] % M;
}

LL power(LL m, LL n) {
  if (!n)
    return 1;
  return (n & 1) ? (power(m, n - 1) * m % M) : power(m * m % M, n >> 1);
}
LL inverse(LL n) { return power(n, M - 2); }
void rerooting(const Graph &G) {
  struct DP {
    LL val = 1, size = 0;
    const DP operator+(const DP &o) const {
      auto r(*this);
      r.val *= o.val;
      r.val %= M;
      r.val *= combination(r.size + o.size, o.size);
      r.val %= M;
      r.size += o.size;
      return r;
    }
    const DP operator-(const DP &o) const {
      auto r(*this);
      r.size -= o.size;
      r.val *= inverse(combination(r.size + o.size, o.size));
      r.val %= M;
      r.val *= inverse(o.val);
      r.val %= M;
      return r;
    }
    const DP addRoot() const { return {val, size + 1}; }
  };
  std::vector<DP> dp(G.size());
  std::function<void(Vertex, Vertex)> dfs = [&](Vertex v, Vertex p) {
    for (const auto &e : G[v])
      if (e.to != p) {
        dfs(e.to, e.from);
        dp[v] = dp[v] + dp[e.to].addRoot();
      }
  };
  std::function<void(Vertex, Vertex)> rev = [&](Vertex v, Vertex p) {
    for (const auto &e : G[v])
      if (e.to != p) {
        dp[e.to] = dp[e.to] + (dp[v] - dp[e.to].addRoot()).addRoot();
        rev(e.to, e.from);
      }
  };
  dfs(0, -1);
  rev(0, -1);
  for (auto v = 0; v < G.size(); ++v)
    cout << dp[v].addRoot().val << endl;
}

int main() {
  int N;
  cin >> N;
  Graph G(N);
  for (auto i = 1; i < N; ++i) {
    int a, b;
    cin >> a >> b;
    --a;
    --b;
    G[a].push_back({a, b});
    G[b].push_back({b, a});
  }
  rerooting(G);
}


Error: TLE

Fixed submission:

#include <bits/stdc++.h>
using namespace std;

using Size = int;
using Vertex = int;
using Weight = long long;
struct Edge {
  Vertex from, to;
  Weight weight;
};
using Graph = std::vector<std::vector<Edge>>;

using LL = long long;
const LL M = 1e9 + 7;

LL combination(LL n, LL r) {
  if (n < r)
    return 0;
  if (n < 0 || r < 0)
    return 0;
  static std::vector<LL> fact{1, 1}, inv{1, 1}, finv{1, 1};
  for (LL i = fact.size(); i <= n; ++i) {
    fact.emplace_back(fact.back() * i % M);
    inv.emplace_back(inv.at(M % i) * (M - M / i) % M);
    finv.emplace_back(finv.back() * inv.back() % M);
  }
  return (fact[n] * finv[n - r] % M) * finv[r] % M;
}

LL inverse(LL n) {
  static std::vector<LL> memo = {1, 1};
  while (LL(memo.size()) <= n)
    memo.emplace_back(memo[M % LL(memo.size())] * (M - M / LL(memo.size())) %
                      M);
  return memo.at(n);
}
void rerooting(const Graph &G) {
  struct DP {
    LL val = 1, size = 0;
    const DP operator+(const DP &o) const {
      auto r(*this);
      r.val *= o.val;
      r.val %= M;
      r.val *= combination(r.size + o.size, o.size);
      r.val %= M;
      r.size += o.size;
      return r;
    }
    const DP operator-(const DP &o) const {
      auto r(*this);
      r.size -= o.size;
      r.val *= inverse(combination(r.size + o.size, o.size));
      r.val %= M;
      r.val *= inverse(o.val);
      r.val %= M;
      return r;
    }
    const DP addRoot() const { return {val, size + 1}; }
  };
  std::vector<DP> dp(G.size());
  std::function<void(Vertex, Vertex)> dfs = [&](Vertex v, Vertex p) {
    for (const auto &e : G[v])
      if (e.to != p) {
        dfs(e.to, e.from);
        dp[v] = dp[v] + dp[e.to].addRoot();
      }
  };
  std::function<void(Vertex, Vertex)> rev = [&](Vertex v, Vertex p) {
    for (const auto &e : G[v])
      if (e.to != p) {
        dp[e.to] = dp[e.to] + (dp[v] - dp[e.to].addRoot()).addRoot();
        rev(e.to, e.from);
      }
  };
  dfs(0, -1);
  rev(0, -1);
  for (auto v = 0; v < G.size(); ++v)
    cout << dp[v].addRoot().val << endl;
}

int main() {
  int N;
  cin >> N;
  Graph G(N);
  for (auto i = 1; i < N; ++i) {
    int a, b;
    cin >> a >> b;
    --a;
    --b;
    G[a].push_back({a, b});
    G[b].push_back({b, a});
  }
  rerooting(G);
}