#define _GLIBCXX_DEBUG
#include <bits/stdc++.h>
using namespace std;
template<typename T> bool chmax(T &a,T b) {if(a<b) {a=b; return true;} return false;}
template<typename T> bool chmin(T &a,T b) {if(a>b) {a=b; return true;} return false;}
#define itn int
#define fi first
#define se second
#define rep(i,n) for(int i=0;i<(int)(n);i++)
#define rep1(i,n) for(int i=1;i<=(int)(n);i++)
#define rrep(i,n) for(int i=(int)(n)-1;i>=0;i--)
#define rrep1(i,n) for(int i=(int)(n);i>=1;i--)
#define all(vec) vec.begin(),vec.end()
#define sortt(vec) sort((vec).begin(),(vec).end())
#define rsort(vec) sort((vec).rbegin(), (vec).rend())
typedef long long ll;
typedef long double ld;
typedef pair<ll,ll> pll;
typedef pair<int,int> pii;
typedef tuple<ll,ll,ll> tlll;
typedef tuple<int,int,int> tiii;
const ll mod=1e9+7;
const int inf=2e9;
const ll lnf=9e18;

struct mint {
  ll x; // typedef long long ll;
  mint(ll x=0):x((x%mod+mod)%mod){}
  mint operator-() const { return mint(-x);}
  mint& operator+=(const mint a) {
    if ((x += a.x) >= mod) x -= mod;
    return *this;
  }
  mint& operator-=(const mint a) {
    if ((x += mod-a.x) >= mod) x -= mod;
    return *this;
  }
  mint& operator*=(const mint a) { (x *= a.x) %= mod; return *this;}
  mint operator+(const mint a) const { return mint(*this) += a;}
  mint operator-(const mint a) const { return mint(*this) -= a;}
  mint operator*(const mint a) const { return mint(*this) *= a;}
  mint pow(ll t) const {
    if (!t) return 1;
    mint a = pow(t>>1);
    a *= a;
    if (t&1) a *= *this;
    return a;
  }

  // for prime mod
  mint inv() const { return pow(mod-2);}
  mint& operator/=(const mint a) { return *this *= a.inv();}
  mint operator/(const mint a) const { return mint(*this) /= a;}
};
istream& operator>>(istream& is, mint& a) { return is >> a.x;}
ostream& operator<<(ostream& os, const mint& a) { return os << a.x;}


template<typename T>
struct Comb{
  vector<T> fac,finv,inv,sinv;
  // Comb() {}
  Comb(int MAX_N):fac(MAX_N,1),finv(MAX_N,1),inv(MAX_N,1),sinv(MAX_N,1) {init(MAX_N);}
  void init(int MAX_N){
    fac.assign(MAX_N,1),finv.assign(MAX_N,1),inv.assign(MAX_N,1),sinv.assign(MAX_N,1);
    //fac[0]=fac[1]=1;
    //finv[0]=finv[1]=1;
    //inv[1]=1;
    sinv[0]=0,sinv[1]=1;
    for (int i=2;i<MAX_N;i++){
      fac[i]=fac[i-1]*i;
      inv[i]=-inv[mod%i]*(mod/i);
      finv[i]=finv[i-1]*inv[i];
      sinv[i]=sinv[i-1]+inv[i];
    }
  }
  T com(int n,int k){ //1≦k≦n≦10^7
    if (n<k) return 0;
    if (n<0||k<0) return 0;
    return fac[n]*finv[k]*finv[n-k];
  }
  T per(int n,int k){ //1≦k≦n≦10^7
    if (n<k) return 0;
    if (n<0||k<0) return 0;
    return fac[n]*finv[n-k];
  }
};
Comb<mint> comb(300000);

//Add cominit(); in main function.

/* Rerooting: 全方位木 DP
    問題ごとに以下を書き換える
    - 型DPと単位元
    - 型DPに対する二項演算 fd
    - まとめたDPを用いて新たな部分木のDPを計算する fr
    計算量: O(N)
*/
struct Rerooting{
  /* start 問題ごとに書き換え */
  struct DP{  // DP の型
    mint dp; //求める値
    int s; //木のサイズ(いらない場合あり)
    DP(mint dp_,int s_):dp(dp_),s(s_) {}
  };
  const DP unit_dp=DP(1,0);  // 単位元の定義
  function<DP(DP,DP,long long)> fd=[](DP dp_cum,DP d,long long cost) -> DP{  // ある頂点についている子たちについての処理
    return DP(dp_cum.dp*comb.com(dp_cum.s+d.s,d.s)*d.dp,dp_cum.s+d.s); //各頂点の最大距離       // dp_cum:それまで見た子たちの総和情報
  };                                                                         // d:現 在見ている子
  function<DP(DP)> fr=[](DP d) -> DP{  // 現在見ている頂点についての処理        // cost:現在見ている子と親を結ぶ辺のコスト
    return DP(d.dp,d.s+1);
  };
  /* end 問題ごとに書き換え */

  // グラフの定義
  struct Edge{
    int from; // 使わない場合あり
    int to;
    long long cost; // 使わない場合あり
  };
  using Graph=vector<vector<Edge> >;

  vector<vector<DP> > dp;  // dp[v][i]: vから出るi番目の有向辺に対応する部分木のDP
  vector<DP> ans;         // ans[v]: 頂点vを根とする木の答え
  Graph G;

  Rerooting(int N):G(N){
    dp.resize(N);
    ans.assign(N,unit_dp);
  }

  void add_edge(int a,int b,long long c=1){
    G[a].push_back({a,b,c});
  }
  void build(){
    dfs(0);           // 普通に木DP
    bfs(0,unit_dp);  // 残りの部分木に対応するDPを計算
  }

  DP dfs(int v,int p=-1){  // 頂点v,親p
    DP dp_cum=unit_dp;
    int deg=G[v].size();
    dp[v]=vector<DP>(deg,unit_dp);
    for(int i=0;i<deg;i++){
      int u=G[v][i].to;
      if(u==p) continue;
      dp[v][i]=dfs(u,v);
      dp_cum=fd(dp_cum,dp[v][i],G[v][i].cost);
    }
    return fr(dp_cum);
  }
  void bfs(int v,const DP &dp_p,int p=-1){
    int deg=G[v].size();
    for(int i=0;i<deg;i++){  // 前のbfsで計算した有向辺に対応する部分木のDPを保存
      if(G[v][i].to==p) dp[v][i]=dp_p;
    }

    vector<DP> dp_l(deg+1,unit_dp),dp_r(deg+1,unit_dp);  // 累積的なDP
    for(int i=0;i<deg;i++){
      dp_l[i+1]=fd(dp_l[i],dp[v][i],G[v][i].cost);
    }
    for(int i=deg-1;i>=0;i--){
      dp_r[i]=fd(dp_r[i+1],dp[v][i],G[v][i].cost);
    }
    ans[v]=fr(dp_l[deg]);
    for(int i=0;i<deg;i++){
      int u=G[v][i].to;
      if(u==p) continue;
      bfs(u,fr(fd(dp_l[i],dp_r[i+1],0)),v);  // 累積同士のfdなので、edgeは適当に
    }
  }
};

int main() {
  int n;
  cin >> n;
  Rerooting reroot(n);
  for (int i = 0; i < n - 1; i++) {
    int a, b;
    cin >> a >> b;
    a--, b--;
    reroot.add_edge(a, b);
    reroot.add_edge(b, a);
  }
  reroot.build();

  for (int i = 0; i < n; i++) {
    cout << reroot.ans[i].dp << endl;
  }
}


Measured memory_bytes: 62592