#include <iostream>
#include <vector>
#include <set>
#include <queue>
#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;
constexpr inline int MAX_N = 200009;
int size_ambient_tree;
vector<ll> dp1(MAX_N); // 1回目の探索での結果
vector<ll> dp2(MAX_N); // 最終的な結果
const ll identity = 1; // モノイドの単位元
const int initial_root = 0; // 1回目の根
vector<vector<ll>> accum_l(MAX_N); // 2回目の探索での累積(左から)
vector<vector<ll>> accum_r(MAX_N); // 2回目の探索での累積(右から)
vector<int> sizes_subtree(MAX_N); // initial_root を根としたときの、各ノードを根とする部分木のサイズ
vector<vector<int>> adjs(MAX_N); // 隣接するノードのリスト
vector<int> index_adjs(MAX_N); // 親の何番目の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)
{
  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)
{
  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()
{
  // 入力を取る
  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, -1);
  dfs2(initial_root, -1);

  // 出力
  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;
}



Measured memory_bytes: 44252