Problem p02728 (C++)

Buggy submission (status: Time Limit Exceeded):
#pragma GCC optimize("Ofast")
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <tuple>
#include <vector>

using namespace std;

using ll = long long int;
using pii = pair<int, int>;
using pil = pair<int, ll>;
using pli = pair<ll, int>;
using pll = pair<ll, ll>;
using psi = pair<string, int>;
using pis = pair<int, string>;
using psl = pair<string, ll>;
using pls = pair<ll, string>;
using pss = pair<string, string>;

template <typename T> using vc = vector<T>;
template <typename T> using vvc = vector<vector<T>>;
template <typename T> using vvvc = vector<vector<vector<T>>>;
template <typename T> using vvvvc = vector<vvvc<T>>;
template <typename T> using vvvvvc = vector<vvvvc<T>>;

template <class T, class U> inline constexpr bool chmin(T &a, const U b) {
  if (a <= b)
    return false;
  a = b;
  return true;
}
template <class T, class U> inline constexpr bool chmax(T &a, const U b) {
  if (a >= b)
    return false;
  a = b;
  return true;
}
#define bit(n, k) ((n >> k) & 1)

inline void bin101() {
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  cout << fixed << setprecision(20);
}

template <typename T> inline void Yes(T flag) {
  if (flag)
    cout << "Yes" << endl;
  else
    cout << "No" << endl;
}

template <typename T> inline void YES(T flag) {
  if (flag)
    cout << "YES" << endl;
  else
    cout << "NO" << endl;
}

// 1-indexed vector cin
template <typename T> inline void vin1(vector<T> &v) {
  for (int i = 1; i < v.size(); i++)
    cin >> v[i];
}

// 0-indexed vector cin
template <typename T> inline void vin0(vector<T> &v) {
  for (int i = 0; i < v.size(); i++)
    cin >> v[i];
}

// 1-indexed vector<vector> cin
template <typename T> inline void vin1(vector<vector<T>> &v) {
  for (int i = 1; i < v.size(); i++) {
    for (int j = 1; j < v[i].size(); j++)
      cin >> v[i][j];
  }
}

// 0-indexed vector<vector> cin
template <typename T> inline void vin0(vector<vector<T>> &v) {
  for (int i = 0; i < v.size(); i++) {
    for (int j = 0; j < v[i].size(); j++)
      cin >> v[i][j];
  }
}

// デバッグ
template <typename T> inline void vout(const vector<T> &v) {
  cout << "\nstart\n";
  const int sz = v.size();
  for (int i = 0; i < sz; i++) {
    cout << i << " " << v[i] << '\n';
  }
  cout << "end\n" << endl;
}
// デバッグ
template <typename T> inline void vout(const vvc<T> &v) {
  cout << "\nstart\n";
  const int sz = v.size();
  for (int i = 0; i < sz; i++) {
    int ssz = v[i].size();
    for (int j = 0; j < ssz; j++) {
      cout << i << " " << j << " " << v[i][j] << '\n';
    }
  }
  cout << "\nend\n" << endl;
}

// デバッグ(グリッド)
template <typename T> inline void gvout(const vector<T> &v) {
  cout << "\nstart\n";
  const int sz = v.size();
  for (int i = 0; i < sz; i++) {
    if (i)
      cout << " ";
    cout << v[i];
  }
  cout << "\nend\n" << endl;
}
// デバッグ(グリッド)
template <typename T> inline void gvout(const vvc<T> &v) {
  cout << "\nstart\n";
  const int sz = v.size();
  for (int i = 0; i < sz; i++) {
    int ssz = v[i].size();
    for (int j = 0; j < ssz; j++) {
      if (j)
        cout << " ";
      cout << v[i][j];
    }
    cout << endl;
  }
  cout << "end\n" << endl;
}

// デバッグ
template <typename T> inline void vout(const vvvc<T> &v) {
  cout << "\nstart\n";
  const int sz = v.size();
  for (int i = 0; i < sz; i++) {
    int ssz = v[i].size();
    for (int j = 0; j < ssz; j++) {
      int sssz = v[i][j].size();
      for (int k = 0; k < sssz; k++) {
        cout << i << " " << j << " " << k << " " << v[i][j][k] << '\n';
      }
    }
  }
  cout << "end\n" << endl;
}

// pair cout
template <typename T, typename U>
inline ostream &operator<<(ostream &os, const pair<T, U> &p) {
  os << p.first << " " << p.second;
  return os;
}

// pair cin
template <typename T, typename U>
inline istream &operator>>(istream &is, pair<T, U> &p) {
  is >> p.first >> p.second;
  return is;
}

// ソート
template <typename T> inline void vsort(vector<T> &v) {
  sort(v.begin(), v.end());
}

// 逆順ソート
template <typename T> inline void rvsort(vector<T> &v) {
  sort(v.rbegin(), v.rend());
}

// 要素数a 初期値x
template <typename T> inline vector<T> vmake(int a, T x) {
  return vector<T>(a, x);
}

// data[a][b] 初期値x
template <typename T> inline vector<vector<T>> vmake(int a, int b, T x) {
  return vector<vector<T>>(a, vector<T>(b, x));
}

// data[a][b][c] 初期値x
template <typename T>
inline vector<vector<vector<T>>> vmake(int a, int b, int c, T x) {
  return vector<vector<vector<T>>>(a, vector<vector<T>>(b, vector<T>(c, x)));
}

// data[a][b][c][d]　初期値x
template <typename T>
inline vector<vector<vector<vector<T>>>> vmake(int a, int b, int c, int d,
                                               T x) {
  return vector<vector<vector<vector<T>>>>(a,
                                           vvvc<T>(b, vvc<T>(c, vc<T>(d, x))));
}

// data[a][b][c][d][e] 初期値x
template <typename T>
inline vvvvvc<T> vmake(int a, int b, int c, int d, int e, T x) {
  return vvvvvc<T>(a, vvvvc<T>(b, vvvc<T>(c, vvc<T>(d, vc<T>(e, x)))));
}

// 1ビットの数を返す
inline int popcount(int x) { return __builtin_popcount(x); }
// 1ビットの数を返す
inline int popcount(ll x) { return __builtin_popcountll(x); }

// queのfront() pop()
template <typename T> inline T pop(queue<T> &que) {
  T x = que.front();
  que.pop();
  return x;
}

// priority_que top() pop()
template <typename T> inline T pop(priority_queue<T> &que) {
  T x = que.top();
  que.pop();
  return x;
}

// stack top() pop()
template <typename T> inline T pop(stack<T> &st) {
  T x = st.top();
  st.pop();
  return x;
}

#define SZ(x) ((int)x.size())
#define pb push_back

/*
満たすものの個数を返す
mode:0 x未満
mode:1 x以下の数
mode:2 x以上の数
mode:3 x超
mode:4 x
*/
template <typename T> inline int count_bound(vector<T> &v, T x, int mode) {
  switch (mode) {
  case 0:
    return lower_bound(v.begin(), v.end(), x) - v.begin();
  case 1:
    return upper_bound(v.begin(), v.end(), x) - v.begin();
  case 2:
    return v.end() - lower_bound(v.begin(), v.end(), x);
  case 3:
    return v.end() - upper_bound(v.begin(), v.end(), x);
  case 4:
    return upper_bound(v.begin(), v.end(), x) -
           lower_bound(v.begin(), v.end(), x);
  }
}

/*
mode:0 xより小さい数で最大の数
mode:1 x以下の数で最大の数
mode:2 x以上の数で最小の数
mode:3 xより大きい数で最小の数
*/
template <typename T> inline T value_bound(vector<T> &v, T x, int mode) {
  switch (mode) {
  case 0:
    return *(--lower_bound(v.begin(), v.end(), x));
  case 1:
    return *(--upper_bound(v.begin(), v.end(), x));
  case 2:
    return *lower_bound(v.begin(), v.end(), x);
  case 3:
    return *upper_bound(v.begin(), v.end(), x);
  }
}

constexpr int MAX = 1 << 30;
constexpr ll INF = 1LL << 62;
constexpr ll MOD = 1e9 + 7;
int dx[] = {1, -1, 0, 0}, dy[] = {0, 0, -1, 1};

//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

struct ModInt {
  using u64 = uint_fast64_t;
  u64 a;
  constexpr ModInt() : a(0) {}
  constexpr ModInt(ll x) : a((x >= 0) ? (x % MOD) : (x % MOD + MOD)) {}

  inline constexpr ModInt operator+(const ModInt rhs) const noexcept {
    return ModInt(*this) += rhs;
  }
  inline constexpr ModInt operator-(const ModInt rhs) const noexcept {
    return ModInt(*this) -= rhs;
  }
  inline constexpr ModInt operator*(const ModInt rhs) const noexcept {
    return ModInt(*this) *= rhs;
  }
  inline constexpr ModInt operator/(const ModInt rhs) const noexcept {
    return ModInt(*this) /= rhs;
  }
  inline constexpr ModInt operator+(const ll rhs) const noexcept {
    return ModInt(*this) += rhs;
  }
  inline constexpr ModInt operator-(const ll rhs) const noexcept {
    return ModInt(*this) -= rhs;
  }
  inline constexpr ModInt operator*(const ll rhs) const noexcept {
    return ModInt(*this) *= rhs;
  }
  inline constexpr ModInt operator/(const ll rhs) const noexcept {
    return ModInt(*this) /= rhs;
  }

  inline constexpr ModInt &operator+=(const ModInt rhs) noexcept {
    a += rhs.a;
    if (a >= MOD)
      a -= MOD;
    return *this;
  }
  inline constexpr ModInt &operator-=(const ModInt rhs) noexcept {
    if (rhs.a > a)
      a += MOD;
    a -= rhs.a;
    return *this;
  }
  inline constexpr ModInt &operator*=(const ModInt rhs) noexcept {
    a = (a * rhs.a) % MOD;
    return *this;
  }
  inline constexpr ModInt &operator/=(ModInt rhs) noexcept {
    a = (a * rhs.inverse().a) % MOD;
    return *this;
  }
  inline constexpr ModInt &operator+=(const ll rhs) noexcept {
    a += rhs;
    if (a >= MOD)
      a -= MOD;
    return *this;
  }
  inline constexpr ModInt &operator-=(const ll rhs) noexcept {
    if (rhs > a)
      a += MOD;
    a -= rhs;
    return *this;
  }
  inline constexpr ModInt &operator*=(const ll rhs) noexcept {
    a = (a * rhs) % MOD;
    return *this;
  }
  inline constexpr ModInt &operator/=(ll rhs) noexcept {
    a = (a * ModInt(rhs).inverse().a) % MOD;
    return *this;
  }

  inline constexpr ModInt operator=(ll x) noexcept {
    x %= MOD;
    if (x < 0)
      x += MOD;
    a = x;
    return *this;
  }

  inline constexpr bool operator==(const ModInt p) const noexcept {
    return a == p.a;
  }

  inline constexpr bool operator!=(const ModInt p) const noexcept {
    return a != p.a;
  }

  inline constexpr ModInt pow(ll N) const noexcept {
    ModInt ans(1LL), p(a);
    while (N > 0) {
      if (bit(N, 0)) {
        ans *= p;
      }
      p *= p;
      N >>= 1;
    }
    return ans;
  }
  inline constexpr ModInt inverse() const noexcept { return pow(MOD - 2); }
};
inline constexpr ModInt operator+(const ll &a, const ModInt &b) noexcept {
  return ModInt(a) += b;
}
inline constexpr ModInt operator-(const ll &a, const ModInt &b) noexcept {
  return ModInt(a) -= b;
}
inline constexpr ModInt operator*(const ll &a, const ModInt &b) noexcept {
  return ModInt(a) *= b;
}
inline constexpr ModInt operator/(const ll &a, const ModInt &b) noexcept {
  return ModInt(a) /= b;
}
// cout
inline ostream &operator<<(ostream &os, const ModInt &p) { return os << p.a; }

// cin
inline istream &operator>>(istream &is, ModInt &p) {
  ll t;
  is >> t;
  p = t;
  return is;
}

inline constexpr ModInt Mr(ll p) {
  p %= MOD;
  if (p < 0)
    p += MOD;
  return ModInt(p);
}
struct Binominal {
  vector<ModInt> fac, finv, inv; // fac[n]:n! finv:(n!)の逆元
  int sz;
  Binominal(int n = 10) : sz(0) {
    if (n == 0)
      n = 10;
    init(n);
  }
  inline void init(int n) {
    fac.resize(n + 1, 1);
    finv.resize(n + 1, 1);
    inv.resize(n + 1, 1);
    for (int i = 2; i <= n; i++) {
      fac[i] = fac[i - 1] * i;
      inv[i] = MOD - inv[MOD % i] * (MOD / i);
      finv[i] = finv[i - 1] * inv[i];
    }
    sz = n;
  }
  // nCk(n,k<=N) をO(1)で求める
  inline ModInt com(int n, int k) {
    if (n < k)
      return ModInt(0);
    if (n < 0 || k < 0)
      return ModInt(0);
    if (n > sz)
      init(n);
    return fac[n] * finv[k] * finv[n - k];
  }
  // nCk(k<=N) をO(k)　で求める
  inline ModInt rcom(ll n, int k) {
    if (n < 0 || k < 0 || n < k)
      return ModInt(0);
    if (k > sz)
      init(k);
    ModInt ret(1);
    for (int i = 0; i < k; i++) {
      ret *= (n - i);
    }
    ret *= finv[k];
    return ret;
  }

  // 重複組み合わせ n種類のものから重複を許してk個を選ぶ
  // 〇がn個,|がk個
  inline ModInt h(int n, int k) { return com(n + k - 1, k); }
};

Binominal B;

// Tはdp(頂点)の型　Dataは辺のコスト
template <typename T, typename Data> struct ReRooting {
  struct Node {
    int to, rev;
    Data data;
    Node(int to, int rev, Data data) : to(to), rev(rev), data(data) {}
  };

  using F1 = function<T(T, T)>;    // 頂点と頂点
  using F2 = function<T(T, Data)>; // 頂点と辺

  vector<vector<Node>> g;
  vector<vector<T>> ldp, rdp;
  vector<int> lptr, rptr;
  const F1 f1;
  const F2 f2;
  const T ident; // Tの単位元 ex.最小値を求める場合はinf

  ReRooting(int n, const F1 &f1, const F2 &f2, const T &ident)
      : g(n), ldp(n), rdp(n), lptr(n), rptr(n), f1(f1), f2(f2), ident(ident) {}

  void add_edge(int u, int v, const Data &d) {
    g[u].emplace_back(v, g[v].size(), d);
    g[v].emplace_back(u, (int)g[u].size() - 1, d);
  }
  // 注意が必要 u->vを実際に使うときはeの値を使う
  void add_edge(int u, int v, const Data &d, const Data &e) {
    g[u].emplace_back(v, g[v].size(), d);
    g[v].emplace_back(u, (int)g[u].size() - 1, e);
  }

  T dfs(int idx, int par) {
    while (lptr[idx] != par && lptr[idx] < g[idx].size()) {
      auto &e = g[idx][lptr[idx]];
      ldp[idx][lptr[idx] + 1] =
          f1(ldp[idx][lptr[idx]], f2(dfs(e.to, e.rev), e.data));
      lptr[idx]++;
    }

    while (rptr[idx] != par && rptr[idx] >= 0) {
      auto &e = g[idx][rptr[idx]];
      rdp[idx][rptr[idx]] =
          f1(rdp[idx][rptr[idx] + 1], f2(dfs(e.to, e.rev), e.data));
      rptr[idx]--;
    }
    if (par < 0)
      return rdp[idx][0];
    return f1(ldp[idx][par], rdp[idx][par + 1]);
  }

  vector<T> solve() {
    for (int i = 0; i < g.size(); i++) {
      // cout<<i<<endl;
      ldp[i].assign(g[i].size() + 1, ident);
      rdp[i].assign(g[i].size() + 1, ident);
      lptr[i] = 0;
      rptr[i] = (int)g[i].size() - 1;
    }
    vector<T> ret;
    // cout<<000<<endl;
    for (int i = 0; i < g.size(); i++) {
      // cout<<i<<endl;
      ret.push_back(dfs(i, -1));
    }
    return ret;
  }
};

signed main() {
  bin101();
  int N;
  cin >> N;
  using tm = tuple<int, ModInt>;

  auto f1 = [](tm a, tm b) {
    return tm(get<0>(a) + get<0>(b),
              get<1>(a) * get<1>(b) * B.com(get<0>(a) + get<0>(b), get<0>(a)));
  };
  auto f2 = [](tm a, int b) {
    get<0>(a)++;
    return a;
  };

  ReRooting<tm, int> root(N, f1, f2, tm(0, Mr(1)));

  for (int i = 0; i < N - 1; i++) {
    int a, b;
    cin >> a >> b;
    a--;
    b--;
    root.add_edge(a, b, 0);
  }
  auto ret = root.solve();
  // cout<<1<<endl;
  for (int i = 0; i < ret.size(); i++) {
    int aa;
    ModInt ab;
    tie(aa, ab) = ret[i];
    cout << ab << "\n";
  }
}


Fixed submission:
#pragma GCC optimize("Ofast")
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <tuple>
#include <vector>

using namespace std;

using ll = long long int;
using pii = pair<int, int>;
using pil = pair<int, ll>;
using pli = pair<ll, int>;
using pll = pair<ll, ll>;
using psi = pair<string, int>;
using pis = pair<int, string>;
using psl = pair<string, ll>;
using pls = pair<ll, string>;
using pss = pair<string, string>;

template <typename T> using vc = vector<T>;
template <typename T> using vvc = vector<vector<T>>;
template <typename T> using vvvc = vector<vector<vector<T>>>;
template <typename T> using vvvvc = vector<vvvc<T>>;
template <typename T> using vvvvvc = vector<vvvvc<T>>;

template <class T, class U> inline constexpr bool chmin(T &a, const U b) {
  if (a <= b)
    return false;
  a = b;
  return true;
}
template <class T, class U> inline constexpr bool chmax(T &a, const U b) {
  if (a >= b)
    return false;
  a = b;
  return true;
}
#define bit(n, k) ((n >> k) & 1)

inline void bin101() {
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  cout << fixed << setprecision(20);
}

template <typename T> inline void Yes(T flag) {
  if (flag)
    cout << "Yes" << endl;
  else
    cout << "No" << endl;
}

template <typename T> inline void YES(T flag) {
  if (flag)
    cout << "YES" << endl;
  else
    cout << "NO" << endl;
}

// 1-indexed vector cin
template <typename T> inline void vin1(vector<T> &v) {
  for (int i = 1; i < v.size(); i++)
    cin >> v[i];
}

// 0-indexed vector cin
template <typename T> inline void vin0(vector<T> &v) {
  for (int i = 0; i < v.size(); i++)
    cin >> v[i];
}

// 1-indexed vector<vector> cin
template <typename T> inline void vin1(vector<vector<T>> &v) {
  for (int i = 1; i < v.size(); i++) {
    for (int j = 1; j < v[i].size(); j++)
      cin >> v[i][j];
  }
}

// 0-indexed vector<vector> cin
template <typename T> inline void vin0(vector<vector<T>> &v) {
  for (int i = 0; i < v.size(); i++) {
    for (int j = 0; j < v[i].size(); j++)
      cin >> v[i][j];
  }
}

// デバッグ
template <typename T> inline void vout(const vector<T> &v) {
  cout << "\nstart\n";
  const int sz = v.size();
  for (int i = 0; i < sz; i++) {
    cout << i << " " << v[i] << '\n';
  }
  cout << "end\n" << endl;
}
// デバッグ
template <typename T> inline void vout(const vvc<T> &v) {
  cout << "\nstart\n";
  const int sz = v.size();
  for (int i = 0; i < sz; i++) {
    int ssz = v[i].size();
    for (int j = 0; j < ssz; j++) {
      cout << i << " " << j << " " << v[i][j] << '\n';
    }
  }
  cout << "\nend\n" << endl;
}

// デバッグ(グリッド)
template <typename T> inline void gvout(const vector<T> &v) {
  cout << "\nstart\n";
  const int sz = v.size();
  for (int i = 0; i < sz; i++) {
    if (i)
      cout << " ";
    cout << v[i];
  }
  cout << "\nend\n" << endl;
}
// デバッグ(グリッド)
template <typename T> inline void gvout(const vvc<T> &v) {
  cout << "\nstart\n";
  const int sz = v.size();
  for (int i = 0; i < sz; i++) {
    int ssz = v[i].size();
    for (int j = 0; j < ssz; j++) {
      if (j)
        cout << " ";
      cout << v[i][j];
    }
    cout << endl;
  }
  cout << "end\n" << endl;
}

// デバッグ
template <typename T> inline void vout(const vvvc<T> &v) {
  cout << "\nstart\n";
  const int sz = v.size();
  for (int i = 0; i < sz; i++) {
    int ssz = v[i].size();
    for (int j = 0; j < ssz; j++) {
      int sssz = v[i][j].size();
      for (int k = 0; k < sssz; k++) {
        cout << i << " " << j << " " << k << " " << v[i][j][k] << '\n';
      }
    }
  }
  cout << "end\n" << endl;
}

// pair cout
template <typename T, typename U>
inline ostream &operator<<(ostream &os, const pair<T, U> &p) {
  os << p.first << " " << p.second;
  return os;
}

// pair cin
template <typename T, typename U>
inline istream &operator>>(istream &is, pair<T, U> &p) {
  is >> p.first >> p.second;
  return is;
}

// ソート
template <typename T> inline void vsort(vector<T> &v) {
  sort(v.begin(), v.end());
}

// 逆順ソート
template <typename T> inline void rvsort(vector<T> &v) {
  sort(v.rbegin(), v.rend());
}

// 要素数a 初期値x
template <typename T> inline vector<T> vmake(int a, T x) {
  return vector<T>(a, x);
}

// data[a][b] 初期値x
template <typename T> inline vector<vector<T>> vmake(int a, int b, T x) {
  return vector<vector<T>>(a, vector<T>(b, x));
}

// data[a][b][c] 初期値x
template <typename T>
inline vector<vector<vector<T>>> vmake(int a, int b, int c, T x) {
  return vector<vector<vector<T>>>(a, vector<vector<T>>(b, vector<T>(c, x)));
}

// data[a][b][c][d]　初期値x
template <typename T>
inline vector<vector<vector<vector<T>>>> vmake(int a, int b, int c, int d,
                                               T x) {
  return vector<vector<vector<vector<T>>>>(a,
                                           vvvc<T>(b, vvc<T>(c, vc<T>(d, x))));
}

// data[a][b][c][d][e] 初期値x
template <typename T>
inline vvvvvc<T> vmake(int a, int b, int c, int d, int e, T x) {
  return vvvvvc<T>(a, vvvvc<T>(b, vvvc<T>(c, vvc<T>(d, vc<T>(e, x)))));
}

// 1ビットの数を返す
inline int popcount(int x) { return __builtin_popcount(x); }
// 1ビットの数を返す
inline int popcount(ll x) { return __builtin_popcountll(x); }

// queのfront() pop()
template <typename T> inline T pop(queue<T> &que) {
  T x = que.front();
  que.pop();
  return x;
}

// priority_que top() pop()
template <typename T> inline T pop(priority_queue<T> &que) {
  T x = que.top();
  que.pop();
  return x;
}

// stack top() pop()
template <typename T> inline T pop(stack<T> &st) {
  T x = st.top();
  st.pop();
  return x;
}

#define SZ(x) ((int)x.size())
#define pb push_back

/*
満たすものの個数を返す
mode:0 x未満
mode:1 x以下の数
mode:2 x以上の数
mode:3 x超
mode:4 x
*/
template <typename T> inline int count_bound(vector<T> &v, T x, int mode) {
  switch (mode) {
  case 0:
    return lower_bound(v.begin(), v.end(), x) - v.begin();
  case 1:
    return upper_bound(v.begin(), v.end(), x) - v.begin();
  case 2:
    return v.end() - lower_bound(v.begin(), v.end(), x);
  case 3:
    return v.end() - upper_bound(v.begin(), v.end(), x);
  case 4:
    return upper_bound(v.begin(), v.end(), x) -
           lower_bound(v.begin(), v.end(), x);
  }
}

/*
mode:0 xより小さい数で最大の数
mode:1 x以下の数で最大の数
mode:2 x以上の数で最小の数
mode:3 xより大きい数で最小の数
*/
template <typename T> inline T value_bound(vector<T> &v, T x, int mode) {
  switch (mode) {
  case 0:
    return *(--lower_bound(v.begin(), v.end(), x));
  case 1:
    return *(--upper_bound(v.begin(), v.end(), x));
  case 2:
    return *lower_bound(v.begin(), v.end(), x);
  case 3:
    return *upper_bound(v.begin(), v.end(), x);
  }
}

constexpr int MAX = 1 << 30;
constexpr ll INF = 1LL << 62;
constexpr ll MOD = 1e9 + 7;
int dx[] = {1, -1, 0, 0}, dy[] = {0, 0, -1, 1};

//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

struct ModInt {
  using u64 = uint_fast64_t;
  u64 a;
  constexpr ModInt() : a(0) {}
  constexpr ModInt(ll x) : a((x >= 0) ? (x % MOD) : (x % MOD + MOD)) {}

  inline constexpr ModInt operator+(const ModInt rhs) const noexcept {
    return ModInt(*this) += rhs;
  }
  inline constexpr ModInt operator-(const ModInt rhs) const noexcept {
    return ModInt(*this) -= rhs;
  }
  inline constexpr ModInt operator*(const ModInt rhs) const noexcept {
    return ModInt(*this) *= rhs;
  }
  inline constexpr ModInt operator/(const ModInt rhs) const noexcept {
    return ModInt(*this) /= rhs;
  }
  inline constexpr ModInt operator+(const ll rhs) const noexcept {
    return ModInt(*this) += rhs;
  }
  inline constexpr ModInt operator-(const ll rhs) const noexcept {
    return ModInt(*this) -= rhs;
  }
  inline constexpr ModInt operator*(const ll rhs) const noexcept {
    return ModInt(*this) *= rhs;
  }
  inline constexpr ModInt operator/(const ll rhs) const noexcept {
    return ModInt(*this) /= rhs;
  }

  inline constexpr ModInt &operator+=(const ModInt rhs) noexcept {
    a += rhs.a;
    if (a >= MOD)
      a -= MOD;
    return *this;
  }
  inline constexpr ModInt &operator-=(const ModInt rhs) noexcept {
    if (rhs.a > a)
      a += MOD;
    a -= rhs.a;
    return *this;
  }
  inline constexpr ModInt &operator*=(const ModInt rhs) noexcept {
    a = (a * rhs.a) % MOD;
    return *this;
  }
  inline constexpr ModInt &operator/=(ModInt rhs) noexcept {
    a = (a * rhs.inverse().a) % MOD;
    return *this;
  }
  inline constexpr ModInt &operator+=(const ll rhs) noexcept {
    a += rhs;
    if (a >= MOD)
      a -= MOD;
    return *this;
  }
  inline constexpr ModInt &operator-=(const ll rhs) noexcept {
    if (rhs > a)
      a += MOD;
    a -= rhs;
    return *this;
  }
  inline constexpr ModInt &operator*=(const ll rhs) noexcept {
    a = (a * rhs) % MOD;
    return *this;
  }
  inline constexpr ModInt &operator/=(ll rhs) noexcept {
    a = (a * ModInt(rhs).inverse().a) % MOD;
    return *this;
  }

  inline constexpr ModInt operator=(ll x) noexcept {
    x %= MOD;
    if (x < 0)
      x += MOD;
    a = x;
    return *this;
  }

  inline constexpr bool operator==(const ModInt p) const noexcept {
    return a == p.a;
  }

  inline constexpr bool operator!=(const ModInt p) const noexcept {
    return a != p.a;
  }

  inline constexpr ModInt pow(ll N) const noexcept {
    ModInt ans(1LL), p(a);
    while (N > 0) {
      if (bit(N, 0)) {
        ans *= p;
      }
      p *= p;
      N >>= 1;
    }
    return ans;
  }
  inline constexpr ModInt inverse() const noexcept { return pow(MOD - 2); }
};
inline constexpr ModInt operator+(const ll &a, const ModInt &b) noexcept {
  return ModInt(a) += b;
}
inline constexpr ModInt operator-(const ll &a, const ModInt &b) noexcept {
  return ModInt(a) -= b;
}
inline constexpr ModInt operator*(const ll &a, const ModInt &b) noexcept {
  return ModInt(a) *= b;
}
inline constexpr ModInt operator/(const ll &a, const ModInt &b) noexcept {
  return ModInt(a) /= b;
}
// cout
inline ostream &operator<<(ostream &os, const ModInt &p) { return os << p.a; }

// cin
inline istream &operator>>(istream &is, ModInt &p) {
  ll t;
  is >> t;
  p = t;
  return is;
}

inline constexpr ModInt Mr(ll p) {
  p %= MOD;
  if (p < 0)
    p += MOD;
  return ModInt(p);
}
struct Binominal {
  vector<ModInt> fac, finv, inv; // fac[n]:n! finv:(n!)の逆元
  int sz;
  Binominal(int n = 10) : sz(0) {
    if (n == 0)
      n = 10;
    init(n);
  }
  inline void init(int n) {
    fac.resize(n + 1, 1);
    finv.resize(n + 1, 1);
    inv.resize(n + 1, 1);
    for (int i = 2; i <= n; i++) {
      fac[i] = fac[i - 1] * i;
      inv[i] = MOD - inv[MOD % i] * (MOD / i);
      finv[i] = finv[i - 1] * inv[i];
    }
    sz = n;
  }
  // nCk(n,k<=N) をO(1)で求める
  inline ModInt com(int n, int k) {
    if (n < k)
      return ModInt(0);
    if (n < 0 || k < 0)
      return ModInt(0);
    if (n > sz)
      init(n);
    return fac[n] * finv[k] * finv[n - k];
  }
  // nCk(k<=N) をO(k)　で求める
  inline ModInt rcom(ll n, int k) {
    if (n < 0 || k < 0 || n < k)
      return ModInt(0);
    if (k > sz)
      init(k);
    ModInt ret(1);
    for (int i = 0; i < k; i++) {
      ret *= (n - i);
    }
    ret *= finv[k];
    return ret;
  }

  // 重複組み合わせ n種類のものから重複を許してk個を選ぶ
  // 〇がn個,|がk個
  inline ModInt h(int n, int k) { return com(n + k - 1, k); }
};

Binominal B;

// Tはdp(頂点)の型　Dataは辺のコスト
template <typename T, typename Data> struct ReRooting {
  struct Node {
    int to, rev;
    Data data;
    Node(int to, int rev, Data data) : to(to), rev(rev), data(data) {}
  };

  using F1 = function<T(T, T)>;    // 頂点と頂点
  using F2 = function<T(T, Data)>; // 頂点と辺

  vector<vector<Node>> g;
  vector<vector<T>> ldp, rdp;
  vector<int> lptr, rptr;
  const F1 f1;
  const F2 f2;
  const T ident; // Tの単位元 ex.最小値を求める場合はinf

  ReRooting(int n, const F1 &f1, const F2 &f2, const T &ident)
      : g(n), ldp(n), rdp(n), lptr(n), rptr(n), f1(f1), f2(f2), ident(ident) {}

  void add_edge(int u, int v, const Data &d) {
    g[u].emplace_back(v, g[v].size(), d);
    g[v].emplace_back(u, (int)g[u].size() - 1, d);
  }
  // 注意が必要 u->vを実際に使うときはeの値を使う
  void add_edge(int u, int v, const Data &d, const Data &e) {
    g[u].emplace_back(v, g[v].size(), d);
    g[v].emplace_back(u, (int)g[u].size() - 1, e);
  }

  T dfs(int idx, int par) {
    while (lptr[idx] != par && lptr[idx] < g[idx].size()) {
      auto &e = g[idx][lptr[idx]];
      ldp[idx][lptr[idx] + 1] =
          f1(ldp[idx][lptr[idx]], f2(dfs(e.to, e.rev), e.data));
      lptr[idx]++;
    }

    while (rptr[idx] != par && rptr[idx] >= 0) {
      auto &e = g[idx][rptr[idx]];
      rdp[idx][rptr[idx]] =
          f1(rdp[idx][rptr[idx] + 1], f2(dfs(e.to, e.rev), e.data));
      rptr[idx]--;
    }
    if (par < 0)
      return rdp[idx][0];
    return f1(ldp[idx][par], rdp[idx][par + 1]);
  }

  vector<T> solve() {
    for (int i = 0; i < g.size(); i++) {
      // cout<<i<<endl;
      ldp[i].assign(g[i].size() + 1, ident);
      rdp[i].assign(g[i].size() + 1, ident);
      lptr[i] = 0;
      rptr[i] = (int)g[i].size() - 1;
    }
    vector<T> ret;
    // cout<<000<<endl;
    for (int i = 0; i < g.size(); i++) {
      // cout<<i<<endl;
      ret.push_back(dfs(i, -1));
    }
    return ret;
  }
};

signed main() {
  bin101();
  int N;
  cin >> N;
  using tm = tuple<int, ModInt>;
  B.init(210000);
  auto f1 = [](tm a, tm b) {
    return tm(get<0>(a) + get<0>(b),
              get<1>(a) * get<1>(b) * B.com(get<0>(a) + get<0>(b), get<0>(a)));
  };
  auto f2 = [](tm a, int b) {
    get<0>(a)++;
    return a;
  };

  ReRooting<tm, int> root(N, f1, f2, tm(0, Mr(1)));

  for (int i = 0; i < N - 1; i++) {
    int a, b;
    cin >> a >> b;
    a--;
    b--;
    root.add_edge(a, b, 0);
  }
  auto ret = root.solve();
  // cout<<1<<endl;
  for (int i = 0; i < ret.size(); i++) {
    int aa;
    ModInt ab;
    tie(aa, ab) = ret[i];
    cout << ab << "\n";
  }
}