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

#include <algorithm>
#include <iomanip>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <vector>
#define _USE_MATH_DEFINES
#include <cassert>
#include <cctype>
#include <cfloat>
#include <climits>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
using namespace std;

#define EPS 1e-12
#define ull unsigned long long
#define ll long long
#define VI vector<ll>
#define PII pair<ll, ll>
#define VVI vector<vector<ll>>
#define VVVI vector<vector<vector<ll>>>
#define VVVVI vector<vector<vector<vector<ll>>>>
#define REP(i, n) for (ll i = 0, _n = (n); (i) < (ll)_n; ++i)
#define REPR(i, n) for (ll i = (ll)(n)-1; 0 <= (i); --i)
#define RANGE(i, a, b) for (ll i = (ll)a, _b = (ll)(b); (i) < _b; ++i)
#define RANGER(i, a, b) for (ll i = (ll)(b)-1, _a = (ll)(a); (_a) <= i; --i)
#define FOR(i, c)                                                              \\
  for (__typeof((c).begin()) i = (c).begin(); i != (c).end(); ++i)
#define ALL(c) (c).begin(), (c).end()
#define ALLR(c) (c).rbegin(), (c).rend()
#define PB push_back
#define MP(a, b) make_pair(a, b)
#define POPCOUNT __builtin_popcount
#define POPCOUNTLL __builtin_popcountll
#define CLEAR(table, v) memset(table, v, sizeof(table));
#define UNIFORM_DOUBLE(a, b)                                                   \\
  (((b - a) * (double)rand() / RAND_MAX) + a)      // [a, b)
#define UNIFORM_LL(a, b) (ll) UNIFORM_DOUBLE(a, b) // [a, b)
#define IN(v, lo, hi) ((lo) <= (v) && (v) < (hi))
#define DD(v) cout << #v << ": " << v << endl
#define FI first
#define SE second
template <typename T0, typename T1>
std::ostream &operator<<(std::ostream &os, const map<T0, T1> &v) {
  for (typename map<T0, T1>::const_iterator p = v.begin(); p != v.end(); p++) {
    os << p->first << ": " << p->second << " ";
  }
  return os;
}
template <typename T0, typename T1>
std::ostream &operator<<(std::ostream &os, const pair<T0, T1> &v) {
  os << v.first << ": " << v.second << " ";
  return os;
}
template <typename T>
std::ostream &operator<<(std::ostream &os, const vector<T> &v) {
  for (int i = 0; i < (int)v.size(); i++) {
    os << v[i] << " ";
  }
  return os;
}
template <typename T>
std::ostream &operator<<(std::ostream &os, const set<T> &v) {
  vector<T> tmp(v.begin(), v.end());
  os << tmp;
  return os;
}
template <typename T>
std::ostream &operator<<(std::ostream &os, const deque<T> &v) {
  vector<T> tmp(v.begin(), v.end());
  os << tmp;
  return os;
}
template <typename T>
std::ostream &operator<<(std::ostream &os, const vector<vector<T>> &v) {
  for (int i = 0; i < (int)v.size(); i++) {
    os << v[i] << endl;
  }
  return os;
}
template <typename T> void maxUpdate(T &a, T b) { a = max(a, b); }
template <typename T> void minUpdate(T &a, T b) { a = min(a, b); }

#define MOD 1000000007LL
#define INF (1LL << 60)

template <ll MODVAL> struct Modll {
  ll val;
  Modll() : val(0) {}
  Modll(ll v) : val(v) { normalize(); }
  void normalize() { val = (val + MODVAL) % MODVAL; }
  Modll operator+(ll v) { return Modll(val + v); }
  Modll &operator+=(ll v) {
    val += v;
    normalize();
    return *this;
  }
  Modll operator-(ll v) { return Modll(val - v); }
  Modll &operator-=(ll v) {
    val -= v;
    normalize();
    return *this;
  }
  Modll operator*(ll v) { return Modll(val * v); }
  Modll &operator*=(ll v) {
    val *= v;
    normalize();
    return *this;
  }
  Modll operator^(ll e) {
    Modll x(val);
    Modll v(1);
    for (; e; x = x * x, e >>= 1)
      if (e & 1)
        v = v * x;
    return v;
  } // pow
  Modll inv() {
    Modll x(val);
    return x ^ (MODVAL - 2);
  } // MODVAL must be prime number when use this!
  static Modll inv(ll v) { return Modll(v).inv(); }
  operator ll() { return val; }
};
template <ll MODVAL>
std::ostream &operator<<(std::ostream &os, const Modll<MODVAL> &v) {
  os << v.val;
  return os;
}
using modll = Modll<1000000007>;

#define MAXN 200010
modll facts[MAXN];
modll inv_facts[MAXN];
// Call gen_facts() before call this
ll modC(ll n, ll r) {
  assert(0 <= n && n < MAXN);
  assert(0 <= r && r <= n);
  return modll(facts[n]) * inv_facts[r] * inv_facts[n - r];
}
void gen_facts() {
  facts[0] = 1;
  inv_facts[0] = modll::inv(facts[0]);
  RANGE(i, 1, MAXN) facts[i] = facts[i - 1] * modll(i);
  RANGE(i, 1, MAXN) inv_facts[i] = inv_facts[i - 1] * modll::inv(i);
  REP(i, MAXN) assert((facts[i] * inv_facts[i]) == 1);
}

/*
https://github.com/key-moon/Library/blob/master/src/Algorithm/rerooting.csx
keymoon による C# の実装を noshi91 が C++ に移植したものです
*/

#include <functional>
#include <stack>
#include <vector>

template <class T> class ReRooting {
public:
  int NodeCount;

private:
  std::vector<std::vector<int>> Adjacents;
  std::vector<std::vector<int>> IndexForAdjacent;

  std::vector<T> Res;
  std::vector<std::vector<T>> DP;

  T Identity;
  std::function<T(T, T)> Operate;
  std::function<T(T, int)> OperateNode;

public:
  ReRooting(int nodeCount, std::vector<std::vector<int>> edges, T identity,
            std::function<T(T, T)> operate,
            std::function<T(T, int)> operateNode) {
    NodeCount = nodeCount;

    Identity = identity;
    Operate = operate;
    OperateNode = operateNode;

    std::vector<std::vector<int>> adjacents(nodeCount);
    std::vector<std::vector<int>> indexForAdjacents(nodeCount);

    for (int i = 0; i < edges.size(); i++) {
      auto &edge = edges[i];
      indexForAdjacents[edge[0]].push_back(adjacents[edge[1]].size());
      indexForAdjacents[edge[1]].push_back(adjacents[edge[0]].size());
      adjacents[edge[0]].push_back(edge[1]);
      adjacents[edge[1]].push_back(edge[0]);
    }

    Adjacents = std::vector<std::vector<int>>(nodeCount);
    IndexForAdjacent = std::vector<std::vector<int>>(nodeCount);
    for (int i = 0; i < nodeCount; i++) {
      Adjacents[i] = adjacents[i];
      IndexForAdjacent[i] = indexForAdjacents[i];
    }

    DP = std::vector<std::vector<T>>(Adjacents.size());
    Res = std::vector<T>(Adjacents.size());

    for (int i = 0; i < Adjacents.size(); i++)
      DP[i] = std::vector<T>(Adjacents[i].size());
    if (NodeCount > 1)
      Initialize();
    else if (NodeCount == 1)
      Res[0] = OperateNode(Identity, 0);
  }

  T Query(int node) { return Res[node]; }

private:
  void Initialize() {
    std::vector<int> parents(NodeCount);
    std::vector<int> order(NodeCount);

#pragma region InitOrderedTree
    int index = 0;
    std::stack<int> stack;
    stack.push(0);
    parents[0] = -1;
    while (stack.size() > 0) {
      auto node = stack.top();
      stack.pop();
      order[index++] = node;
      for (int i = 0; i < Adjacents[node].size(); i++) {
        auto adjacent = Adjacents[node][i];
        if (adjacent == parents[node])
          continue;
        stack.push(adjacent);
        parents[adjacent] = node;
      }
    }
#pragma endregion

#pragma region fromLeaf
    for (int i = order.size() - 1; i >= 1; i--) {
      auto node = order[i];
      auto parent = parents[node];

      T accum = Identity;
      int parentIndex = -1;
      for (int j = 0; j < Adjacents[node].size(); j++) {
        if (Adjacents[node][j] == parent) {
          parentIndex = j;
          continue;
        }
        accum = Operate(accum, DP[node][j]);
      }
      DP[parent][IndexForAdjacent[node][parentIndex]] =
          OperateNode(accum, node);
    }
#pragma endregion

#pragma region toLeaf
    for (int i = 0; i < order.size(); i++) {
      auto node = order[i];
      T accum = Identity;
      std::vector<T> accumsFromTail(Adjacents[node].size());
      accumsFromTail[accumsFromTail.size() - 1] = Identity;
      for (int j = accumsFromTail.size() - 1; j >= 1; j--)
        accumsFromTail[j - 1] = Operate(DP[node][j], accumsFromTail[j]);
      for (int j = 0; j < accumsFromTail.size(); j++) {
        DP[Adjacents[node][j]][IndexForAdjacent[node][j]] =
            OperateNode(Operate(accum, accumsFromTail[j]), node);
        accum = Operate(accum, DP[node][j]);
      }
      Res[node] = OperateNode(accum, node);
    }
#pragma endregion
  }
};

// そのノード以下の書き方組み合わせ数
vector<modll> dp;
// そのノード含めて親方向の書き方組み合わせ数
vector<modll> dp2;
// そのノード以下のノード数
VI size;
// そのノード含めて親方向のノード数
VI size2;
void dfs(ll cur, ll prev, VVI &g) {
  ll ch = 0;
  for (ll adj : g[cur])
    if (adj != prev)
      ch++;
  if (ch == 0) {
    dp[cur] = 1;
    size[cur] = 1;
    return;
  }
  modll v = 1LL;
  for (ll adj : g[cur])
    if (adj != prev) {
      dfs(adj, cur, g);
      size[cur] += size[adj];
      v *= dp[adj] * inv_facts[size[adj]];
    }
  size[cur]++;
  dp[cur] = facts[size[cur] - 1] * v;
}
void dfs2(ll cur, ll prev, VVI &g) {
  // 自分の分
  size2[cur]++;
  if (prev != -1) {
    size2[cur] += size2[prev];
    // 兄弟ただし自分以外
    size2[cur] += size[prev] - size[cur] - 1;
  }

  /*
  親を塗った後, 親の周りただし自分以外を塗る方法の数
          (size2[prev]-1)!Πdp/size
  親の親方向は
          dp2[prev] / (size2[prev]-1)!
  親の子方向は
          dp[prev]からN!と自分方向の寄与を消したものなので
          dp[prev] / (size[prev]-1)! * size[cur]! / dp[cur]
  */
  //	DD("");
  //	DD(cur);
  //	DD(prev);
  modll v = 1LL;
  if (prev != -1) {
    v *= dp2[prev] * inv_facts[size2[prev] - 1];
    //		DD("parent of parent");
    //		DD(dp2[prev]);
    //		DD(size2[prev]-1);
    //		DD(facts[size2[prev]-1]);
    //		DD(dp2[prev] * inv_facts[size2[prev]-1]);
  }
  if (prev != -1) {
    v *=
        dp[prev] * inv_facts[size[prev] - 1] * facts[size[cur]] * dp[cur].inv();
    //		DD("bro");
    //		DD(dp[prev]);
    //		DD(size[prev]);
    //		DD(facts[size[prev]-1]);
    //		DD(size[cur]);
    //		DD(facts[size[cur]]);
    //		DD(dp[cur]);
    //		DD(dp[prev] * inv_facts[size[prev]-1] * facts[size[cur]] *
    //dp[cur].inv());
  }
  dp2[cur] = 1LL;
  if (prev != -1) {
    dp2[cur] = facts[size2[cur] - 2] * v;
    //		DD("total");
    //		DD(size2[cur]-2);
    //		DD(facts[size2[cur]-2]);
  }
  //	DD(dp2[cur]);
  for (ll adj : g[cur])
    if (adj != prev) {
      dfs2(adj, cur, g);
    }
}

struct NV {
  modll v;
  int size;
  bool div;
};
ostream &operator<<(ostream &o, const NV &nv) {
  o << "v " << nv.v << " size " << nv.size << " div " << nv.div;
  return o;
}
int main() {
  gen_facts();
  cin.tie(0);
  ios::sync_with_stdio(false);
  ll N, A, B;
  while (cin >> N) {
    VVI g(N);
    vector<vector<int>> edges;
    REP(i, N - 1) {
      cin >> A >> B;
      A--;
      B--;
      edges.PB(vector<int>{(int)A, (int)B});
      g[A].PB(B);
      g[B].PB(A);
    }
    auto mergeFun = [&](NV a, NV b) -> NV {
      modll v = a.v * b.v;
      // 常に/?.size!する実装だと,
      // 左から1,1,2とmergeするとき1,1の時点で再度/?.size!してしまって答えが合わない。
      // bだけ割るようにしてもN=0以外でおかしくなる
      // 足した兄弟数が1のときだけ割ると良さそうに見えるがN=0以外でおかしくなる
      if (!a.div)
        v *= inv_facts[a.size];
      if (!b.div)
        v *= inv_facts[b.size];
      auto rv = NV{
          v,
          a.size + b.size,
          true,
      };
      //			cout<<"MergeFun "<<a<<" "<<b<<" result
      //"<<rv<<endl;
      return rv;
    };
    auto nodeFun = [&](NV a, int idx) -> NV {
      auto rv = NV{a.v * facts[a.size], a.size + 1, false};
      //			cout<<"NodeFun "<<a<<" idx "<<idx<<" result
      //"<<rv<<endl;
      return rv;
    };
    ReRooting<NV> rr(N, edges, NV{1LL, 0, false}, mergeFun, nodeFun);
    REP(i, N) { cout << rr.Query(i).v << endl; }
    //		break;

    //		dp = vector<modll>(N);
    //		size = VI(N);
    //		dfs(0, -1, g);
    //		dp2 = vector<modll>(N);
    //		size2 = VI(N);
    //		dfs2(0, -1, g);
    //		REP(i, N) {
    //			/*
    //			(N-1)!*dp2[cur]/(size2[cur]-1)!*dp[cur]/(size[cur]-1)!
    //			*/
    //			modll ans =
    //facts[N-1]*dp2[i]*inv_facts[size2[i]-1]*dp[i]*inv_facts[size[i]-1];
    //			cout<<ans<<endl;
    //		}
  }

  return 0;
}


Error: TLE

Fixed submission:

#include <algorithm>
#include <iomanip>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <vector>
#define _USE_MATH_DEFINES
#include <cassert>
#include <cctype>
#include <cfloat>
#include <climits>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
using namespace std;

#define EPS 1e-12
#define ull unsigned long long
#define ll long long
#define VI vector<ll>
#define PII pair<ll, ll>
#define VVI vector<vector<ll>>
#define VVVI vector<vector<vector<ll>>>
#define VVVVI vector<vector<vector<vector<ll>>>>
#define REP(i, n) for (ll i = 0, _n = (n); (i) < (ll)_n; ++i)
#define REPR(i, n) for (ll i = (ll)(n)-1; 0 <= (i); --i)
#define RANGE(i, a, b) for (ll i = (ll)a, _b = (ll)(b); (i) < _b; ++i)
#define RANGER(i, a, b) for (ll i = (ll)(b)-1, _a = (ll)(a); (_a) <= i; --i)
#define FOR(i, c)                                                              \\
  for (__typeof((c).begin()) i = (c).begin(); i != (c).end(); ++i)
#define ALL(c) (c).begin(), (c).end()
#define ALLR(c) (c).rbegin(), (c).rend()
#define PB push_back
#define MP(a, b) make_pair(a, b)
#define POPCOUNT __builtin_popcount
#define POPCOUNTLL __builtin_popcountll
#define CLEAR(table, v) memset(table, v, sizeof(table));
#define UNIFORM_DOUBLE(a, b)                                                   \\
  (((b - a) * (double)rand() / RAND_MAX) + a)      // [a, b)
#define UNIFORM_LL(a, b) (ll) UNIFORM_DOUBLE(a, b) // [a, b)
#define IN(v, lo, hi) ((lo) <= (v) && (v) < (hi))
#define DD(v) cout << #v << ": " << v << endl
#define FI first
#define SE second
template <typename T0, typename T1>
std::ostream &operator<<(std::ostream &os, const map<T0, T1> &v) {
  for (typename map<T0, T1>::const_iterator p = v.begin(); p != v.end(); p++) {
    os << p->first << ": " << p->second << " ";
  }
  return os;
}
template <typename T0, typename T1>
std::ostream &operator<<(std::ostream &os, const pair<T0, T1> &v) {
  os << v.first << ": " << v.second << " ";
  return os;
}
template <typename T>
std::ostream &operator<<(std::ostream &os, const vector<T> &v) {
  for (int i = 0; i < (int)v.size(); i++) {
    os << v[i] << " ";
  }
  return os;
}
template <typename T>
std::ostream &operator<<(std::ostream &os, const set<T> &v) {
  vector<T> tmp(v.begin(), v.end());
  os << tmp;
  return os;
}
template <typename T>
std::ostream &operator<<(std::ostream &os, const deque<T> &v) {
  vector<T> tmp(v.begin(), v.end());
  os << tmp;
  return os;
}
template <typename T>
std::ostream &operator<<(std::ostream &os, const vector<vector<T>> &v) {
  for (int i = 0; i < (int)v.size(); i++) {
    os << v[i] << endl;
  }
  return os;
}
template <typename T> void maxUpdate(T &a, T b) { a = max(a, b); }
template <typename T> void minUpdate(T &a, T b) { a = min(a, b); }

#define MOD 1000000007LL
#define INF (1LL << 60)

template <ll MODVAL> struct Modll {
  ll val;
  Modll() : val(0) {}
  Modll(ll v) : val(v) { normalize(); }
  void normalize() { val = (val + MODVAL) % MODVAL; }
  Modll operator+(ll v) { return Modll(val + v); }
  Modll &operator+=(ll v) {
    val += v;
    normalize();
    return *this;
  }
  Modll operator-(ll v) { return Modll(val - v); }
  Modll &operator-=(ll v) {
    val -= v;
    normalize();
    return *this;
  }
  Modll operator*(ll v) { return Modll(val * v); }
  Modll &operator*=(ll v) {
    val *= v;
    normalize();
    return *this;
  }
  Modll operator^(ll e) {
    Modll x(val);
    Modll v(1);
    for (; e; x = x * x, e >>= 1)
      if (e & 1)
        v = v * x;
    return v;
  } // pow
  Modll inv() {
    Modll x(val);
    return x ^ (MODVAL - 2);
  } // MODVAL must be prime number when use this!
  static Modll inv(ll v) { return Modll(v).inv(); }
  operator ll() { return val; }
};
template <ll MODVAL>
std::ostream &operator<<(std::ostream &os, const Modll<MODVAL> &v) {
  os << v.val;
  return os;
}
using modll = Modll<1000000007>;

#define MAXN 200010
modll facts[MAXN];
modll inv_facts[MAXN];
// Call gen_facts() before call this
ll modC(ll n, ll r) {
  assert(0 <= n && n < MAXN);
  assert(0 <= r && r <= n);
  return modll(facts[n]) * inv_facts[r] * inv_facts[n - r];
}
void gen_facts() {
  facts[0] = 1;
  inv_facts[0] = modll::inv(facts[0]);
  RANGE(i, 1, MAXN) facts[i] = facts[i - 1] * modll(i);
  RANGE(i, 1, MAXN) inv_facts[i] = inv_facts[i - 1] * modll::inv(i);
  REP(i, MAXN) assert((facts[i] * inv_facts[i]) == 1);
}

/*
https://github.com/key-moon/Library/blob/master/src/Algorithm/rerooting.csx
keymoon による C# の実装を noshi91 が C++ に移植したものです
*/

#include <functional>
#include <stack>
#include <vector>

template <class T> class ReRooting {
public:
  int NodeCount;

private:
  std::vector<std::vector<int>> Adjacents;
  std::vector<std::vector<int>> IndexForAdjacent;

  std::vector<T> Res;
  std::vector<std::vector<T>> DP;

  T Identity;
  std::function<T(T, T)> Operate;
  std::function<T(T, int)> OperateNode;

public:
  ReRooting(int nodeCount, std::vector<std::vector<int>> edges, T identity,
            std::function<T(T, T)> operate,
            std::function<T(T, int)> operateNode) {
    NodeCount = nodeCount;

    Identity = identity;
    Operate = operate;
    OperateNode = operateNode;

    std::vector<std::vector<int>> adjacents(nodeCount);
    std::vector<std::vector<int>> indexForAdjacents(nodeCount);

    for (int i = 0; i < edges.size(); i++) {
      auto &edge = edges[i];
      indexForAdjacents[edge[0]].push_back(adjacents[edge[1]].size());
      indexForAdjacents[edge[1]].push_back(adjacents[edge[0]].size());
      adjacents[edge[0]].push_back(edge[1]);
      adjacents[edge[1]].push_back(edge[0]);
    }

    Adjacents = std::vector<std::vector<int>>(nodeCount);
    IndexForAdjacent = std::vector<std::vector<int>>(nodeCount);
    for (int i = 0; i < nodeCount; i++) {
      Adjacents[i] = adjacents[i];
      IndexForAdjacent[i] = indexForAdjacents[i];
    }

    DP = std::vector<std::vector<T>>(Adjacents.size());
    Res = std::vector<T>(Adjacents.size());

    for (int i = 0; i < Adjacents.size(); i++)
      DP[i] = std::vector<T>(Adjacents[i].size());
    if (NodeCount > 1)
      Initialize();
    else if (NodeCount == 1)
      Res[0] = OperateNode(Identity, 0);
  }

  T Query(int node) { return Res[node]; }

private:
  void Initialize() {
    std::vector<int> parents(NodeCount);
    std::vector<int> order(NodeCount);

#pragma region InitOrderedTree
    int index = 0;
    std::stack<int> stack;
    stack.push(0);
    parents[0] = -1;
    while (stack.size() > 0) {
      auto node = stack.top();
      stack.pop();
      order[index++] = node;
      for (int i = 0; i < Adjacents[node].size(); i++) {
        auto adjacent = Adjacents[node][i];
        if (adjacent == parents[node])
          continue;
        stack.push(adjacent);
        parents[adjacent] = node;
      }
    }
#pragma endregion

#pragma region fromLeaf
    for (int i = order.size() - 1; i >= 1; i--) {
      auto node = order[i];
      auto parent = parents[node];

      T accum = Identity;
      int parentIndex = -1;
      for (int j = 0; j < Adjacents[node].size(); j++) {
        if (Adjacents[node][j] == parent) {
          parentIndex = j;
          continue;
        }
        accum = Operate(accum, DP[node][j]);
      }
      DP[parent][IndexForAdjacent[node][parentIndex]] =
          OperateNode(accum, node);
    }
#pragma endregion

#pragma region toLeaf
    for (int i = 0; i < order.size(); i++) {
      auto node = order[i];
      T accum = Identity;
      std::vector<T> accumsFromTail(Adjacents[node].size());
      accumsFromTail[accumsFromTail.size() - 1] = Identity;
      for (int j = accumsFromTail.size() - 1; j >= 1; j--)
        accumsFromTail[j - 1] = Operate(DP[node][j], accumsFromTail[j]);
      for (int j = 0; j < accumsFromTail.size(); j++) {
        DP[Adjacents[node][j]][IndexForAdjacent[node][j]] =
            OperateNode(Operate(accum, accumsFromTail[j]), node);
        accum = Operate(accum, DP[node][j]);
      }
      Res[node] = OperateNode(accum, node);
    }
#pragma endregion
  }
};

// そのノード以下の書き方組み合わせ数
vector<modll> dp;
// そのノード含めて親方向の書き方組み合わせ数
vector<modll> dp2;
// そのノード以下のノード数
VI size;
// そのノード含めて親方向のノード数
VI size2;
void dfs(ll cur, ll prev, VVI &g) {
  ll ch = 0;
  for (ll adj : g[cur])
    if (adj != prev)
      ch++;
  if (ch == 0) {
    dp[cur] = 1;
    size[cur] = 1;
    return;
  }
  modll v = 1LL;
  for (ll adj : g[cur])
    if (adj != prev) {
      dfs(adj, cur, g);
      size[cur] += size[adj];
      v *= dp[adj] * inv_facts[size[adj]];
    }
  size[cur]++;
  dp[cur] = facts[size[cur] - 1] * v;
}
void dfs2(ll cur, ll prev, VVI &g) {
  // 自分の分
  size2[cur]++;
  if (prev != -1) {
    size2[cur] += size2[prev];
    // 兄弟ただし自分以外
    size2[cur] += size[prev] - size[cur] - 1;
  }

  /*
  親を塗った後, 親の周りただし自分以外を塗る方法の数
          (size2[prev]-1)!Πdp/size
  親の親方向は
          dp2[prev] / (size2[prev]-1)!
  親の子方向は
          dp[prev]からN!と自分方向の寄与を消したものなので
          dp[prev] / (size[prev]-1)! * size[cur]! / dp[cur]
  */
  //	DD("");
  //	DD(cur);
  //	DD(prev);
  modll v = 1LL;
  if (prev != -1) {
    v *= dp2[prev] * inv_facts[size2[prev] - 1];
    //		DD("parent of parent");
    //		DD(dp2[prev]);
    //		DD(size2[prev]-1);
    //		DD(facts[size2[prev]-1]);
    //		DD(dp2[prev] * inv_facts[size2[prev]-1]);
  }
  if (prev != -1) {
    v *=
        dp[prev] * inv_facts[size[prev] - 1] * facts[size[cur]] * dp[cur].inv();
    //		DD("bro");
    //		DD(dp[prev]);
    //		DD(size[prev]);
    //		DD(facts[size[prev]-1]);
    //		DD(size[cur]);
    //		DD(facts[size[cur]]);
    //		DD(dp[cur]);
    //		DD(dp[prev] * inv_facts[size[prev]-1] * facts[size[cur]] *
    //dp[cur].inv());
  }
  dp2[cur] = 1LL;
  if (prev != -1) {
    dp2[cur] = facts[size2[cur] - 2] * v;
    //		DD("total");
    //		DD(size2[cur]-2);
    //		DD(facts[size2[cur]-2]);
  }
  //	DD(dp2[cur]);
  for (ll adj : g[cur])
    if (adj != prev) {
      dfs2(adj, cur, g);
    }
}

struct NV {
  modll v;
  int size;
  bool div;
  VI indices;
};
ostream &operator<<(ostream &o, const NV &nv) {
  o << "v " << nv.v << " size " << nv.size << " sib " << nv.div << " indices "
    << nv.indices;
  return o;
}
int main() {
  gen_facts();
  cin.tie(0);
  ios::sync_with_stdio(false);
  ll N, A, B;
  while (cin >> N) {
    VVI g(N);
    vector<vector<int>> edges;
    REP(i, N - 1) {
      cin >> A >> B;
      A--;
      B--;
      edges.PB(vector<int>{(int)A, (int)B});
      g[A].PB(B);
      g[B].PB(A);
    }
    auto mergeFun = [&](NV a, NV b) -> NV {
      VI abi;
      for (auto e : a.indices)
        abi.PB(e);
      for (auto e : b.indices)
        abi.PB(e);
      modll v = a.v * b.v;
      // 常に/?.size!する実装だと,
      // 左から1,1,2とmergeするとき1,1の時点で再度/?.size!してしまって答えが合わない。
      // bだけ割るようにしてもN=0以外でおかしくなる
      // 足した兄弟数が1のときだけ割ると良さそうに見えるがN=0以外でおかしくなる
      if (!a.div)
        v *= inv_facts[a.size];
      if (!b.div)
        v *= inv_facts[b.size];
      auto rv = NV{
          v,
          a.size + b.size,
          true,
          abi,
      };
      //			cout<<"MergeFun "<<a<<" "<<b<<" result
      //"<<rv<<endl;
      return rv;
    };
    auto nodeFun = [&](NV a, int idx) -> NV {
      auto rv = NV{a.v * facts[a.size], a.size + 1, false, {idx}};
      //			cout<<"NodeFun "<<a<<" idx "<<idx<<" result
      //"<<rv<<endl;
      return rv;
    };
    ReRooting<NV> rr(N, edges, NV{1LL, 0, false}, mergeFun, nodeFun);
    REP(i, N) { cout << rr.Query(i).v << endl; }
    //		break;

    //		dp = vector<modll>(N);
    //		size = VI(N);
    //		dfs(0, -1, g);
    //		dp2 = vector<modll>(N);
    //		size2 = VI(N);
    //		dfs2(0, -1, g);
    //		REP(i, N) {
    //			/*
    //			(N-1)!*dp2[cur]/(size2[cur]-1)!*dp[cur]/(size[cur]-1)!
    //			*/
    //			modll ans =
    //facts[N-1]*dp2[i]*inv_facts[size2[i]-1]*dp[i]*inv_facts[size[i]-1];
    //			cout<<ans<<endl;
    //		}
  }

  return 0;
}