Problem:
Score : 600 points

Problem Statement

We have a tree with N vertices numbered 1 to N. The i-th edge in this tree connects Vertex a_i and b_i.
For each k=1, ..., N, solve the problem below:

Consider writing a number on each vertex in the tree in the following manner:

First, write 1 on Vertex k.

Then, for each of the numbers 2, ..., N in this order, write the number on the vertex chosen as follows:

Choose a vertex that still does not have a number written on it and is adjacent to a vertex with a number already written on it. If there are multiple such vertices, choose one of them at random.

Find the number of ways in which we can write the numbers on the vertices, modulo (10^9+7).

Constraints

2 \leq N \leq 2 \times 10^5

1 \leq a_i,b_i \leq N

The given graph is a tree.

Input

Input is given from Standard Input in the following format:

N
a_1 b_1
:
a_{N-1} b_{N-1}

Output

For each k=1, 2, ..., N in this order, print a line containing the answer to the problem.

Sample Input 1

3
1 2
1 3

Sample Output 1

2
1
1

The graph in this input is as follows:

For k=1, there are two ways in which we can write the numbers on the vertices, as follows:

Writing 1, 2, 3 on Vertex 1, 2, 3, respectively

Writing 1, 3, 2 on Vertex 1, 2, 3, respectively

Sample Input 2

2
1 2

Sample Output 2

1
1

The graph in this input is as follows:

Sample Input 3

5
1 2
2 3
3 4
3 5

Sample Output 3

2
8
12
3
3

The graph in this input is as follows:

Sample Input 4

8
1 2
2 3
3 4
3 5
3 6
6 7
6 8

Sample Output 4

40
280
840
120
120
504
72
72

The graph in this input is as follows:

Solution in C++ (GCC 9.2.1) (judge verdict: Accepted)

#include <iostream>
#include <vector>
#include <set>
#include <queue>
#include <array>
#include <tuple>
#include <string>
#include <algorithm>
#include <functional> // greater など
#include <cmath> // abs など
#include <numeric> // accumulate など
#include <stdexcept>
#include <cassert> // assert
using namespace std;
#define rep(i, n) for (int i = 0; i < (int)(n); i++)
typedef long long ll;

#define NDEBUG 1
// debug
// https://trap.jp/post/998/
void debug_out() { cout << endl; }
template <typename Head, typename... Tail>
void debug_out(Head H, Tail... T)
{
  clog << H << " ";
  debug_out(T...);
}
#ifdef NDEBUG
#define debug(...)
#else
#define debug(...) debug_out(__VA_ARGS__)
#endif

constexpr inline ll bigprime = 1000000007; // 1e9 + 7
constexpr inline int MAX_N = 200009;
int size_ambient_tree;
array<ll, MAX_N> dp1; // 1回目の探索での結果
array<ll, MAX_N> dp2; // 最終的な結果
const ll identity = 1; // モノイドの単位元
const int initial_root = 0; // 1回目の根
array<vector<ll>, MAX_N> accum_l; // 2回目の探索での累積(左から)
array<vector<ll>, MAX_N> accum_r; // 2回目の探索での累積(右から)
array<int, MAX_N> sizes_subtree;  // initial_root を根としたときの、各ノードを根とする部分木のサイズ
array<vector<int>, MAX_N> adjs; // 隣接するノードのリスト
array<int, MAX_N> index_adjs;     // 親の何番目のadjsか？

constexpr ll modpow(ll n, ll k)
{
  if (k < 0)
  {
    throw domain_error("modpow: k must not be negative");
  }
  else if (k == 0)
  {
    return 1;
  }
  else if (k % 2 == 0)
  {
    ll res = modpow(n, k / 2);
    return res * res % bigprime;
  }
  else
  {
    ll res = modpow(n, k - 1);
    return res * n % bigprime;
  }
}

constexpr inline ll modinv(ll n)
{
  ll m = n % bigprime;
  if (m == 0)
  {
    throw domain_error("modinv: 0 is not invertible");
  }
  return modpow(m, bigprime - 2);
}

// 子すべてでの値をマージした値から、あるnodeでの値を得る
// size_subtreeはnodeを含めて数える
constexpr inline ll calc_on_node(int size_subtree, ll merged)
{
  return modinv(size_subtree) * merged % bigprime;
}

// モノイド演算
constexpr inline ll merge(ll x, ll y)
{
  return x * y % bigprime;
}

// 普通の木DPでsize_subtree, dp1, index_adjsを求める
void dfs1(const int node, const int parent = -1)
{
  int size_subtree = 1; // node以下の部分木のサイズ
  ll merged = identity; // nodeの子すべてでの値をマージした値

  // 子を順番に処理
  for (int i = 0; i < adjs.at(node).size(); i++)
  {
    // 親は無視
    const int child = adjs.at(node).at(i);
    if (child == parent)
    {
      continue;
    }

    dfs1(child, node);

    // 値を更新
    index_adjs.at(child) = i;
    size_subtree += sizes_subtree.at(child);
    merged = merge(merged, dp1.at(child));
  }

  // 値を格納
  sizes_subtree.at(node) = size_subtree;
  dp1.at(node) = calc_on_node(size_subtree, merged);
}

// 全方位木DPでdp2を求める
void dfs2(int node, int parent = -1)
{
  ll parent_res; // 全体の木からnode以下の部分木を取り除きparentを根として得られる部分木での値

  // 親がいればparent_resを求める
  // 親がいないなら定義されない
  if (node != initial_root)
  {
    int index = index_adjs.at(node);
    // node以外のparentの子すべてでの値をマージした値
    ll parent_merged = merge(accum_l.at(parent).at(index), accum_r.at(parent).at(index));
    parent_res = calc_on_node(size_ambient_tree - sizes_subtree.at(node), parent_merged);
  }

  // accum_l, accum_r, dp2 を求める
  const int num_adjs = adjs.at(node).size();
  accum_l.at(node).resize(num_adjs + 1); // すべてマージした値も求めておくため+1してある
  accum_l.at(node).at(0) = identity;
  accum_r.at(node).resize(num_adjs);
  accum_r.at(node).at(num_adjs - 1) = identity;
  for (int i = 1; i <= num_adjs; i++)
  {
    int adj = adjs.at(node).at(i - 1);
    ll res = (adj == parent) ? parent_res : dp1.at(adj);
    accum_l.at(node).at(i) = merge(accum_l.at(node).at(i - 1), res);
  }
  for (int i = num_adjs - 2; i >= 0; i--)
  {
    int adj = adjs.at(node).at(i + 1);
    ll res = (adj == parent) ? parent_res : dp1.at(adj);
    accum_r.at(node).at(i) = merge(accum_r.at(node).at(i + 1), res);
  }
  dp2.at(node) = calc_on_node(size_ambient_tree, accum_l.at(node).at(num_adjs));

  // 子についても処理する
  for (const int child : adjs.at(node))
  {
    if (child == parent)
    {
      continue;
    }
    dfs2(child, node);
  }
}

int main()
{
  // 入出力
  ios_base::sync_with_stdio(false);
  cin.tie(nullptr);
  // 入力を取る
  cin >> size_ambient_tree;
  rep(i, size_ambient_tree - 1)
  {
    int a, b;
    cin >> a >> b;
    a--; b--; // 入力では1から始まるのでデクリメントする必要がある!
    adjs.at(a).push_back(b);
    adjs.at(b).push_back(a);
  }

  // 処理
  dfs1(initial_root);
  dfs2(initial_root);

  // 出力
  ll fact = 1;
  rep(i, size_ambient_tree)
  {
    fact = fact * (i + 1) % bigprime;
  }
  rep(i, size_ambient_tree)
  {
    cout << fact * dp2.at(i) % bigprime << '\n';
  }
  return 0;
}