#include <iostream>
#include <string>
#include <vector>
#include <set>
#include <stack>
#include <queue>
#include <map>
#include <algorithm>
#include <iomanip>
#include <math.h>
#include <string.h>
#include <cstdio>
#include <tuple>
#include <numeric>
#include <functional>
using namespace std; using ll = long long; using ld = long double;  using pll = pair<ll, ll>;
using vl = vector<ll>; using vll = vector<vl>; using vlll = vector<vll>; using vpll = vector<pll>;
using vs = vector<string>; using tll = tuple<ll, ll, ll>; using vtll = vector<tll>;
template<class T>bool chmax(T& a, const T& b) { if (a < b) { a = b; return 1; } return 0; }
template<class T>bool chmin(T& a, const T& b) { if (b < a) { a = b; return 1; } return 0; }
const ld PI = 3.1415926535897932;
#define debug(...) cerr << "[" << #__VA_ARGS__ << "]:", debug_out(__VA_ARGS__)
#define mp make_pair
#define mt make_tuple
#define pb push_back
#define co(i) cout << i << endl;
#define co2(i,j) cout << i << " " << j << endl;
#define co3(i) cout << i << " ";
#define po(i) cout << i.first << " " << i.second << endl;
void in() {}
void debug_out() { cerr << endl; }
template<typename Head, typename... Tail>
void debug_out(Head h, Tail... t) {
	cerr << " " << h;
	if (sizeof...(t) > 0) cerr << " :";
	debug_out(t...);
}
template <typename T>
ostream& operator<<(ostream& os, vector<T> vec) {
	for (size_t i = 0; i < vec.size(); i++)os << vec[i] << (i + 1 == vec.size() ? "" : " ");
	return os;
}
ll ctoi(char c) {
	switch (c) {
	case '0': return 0; case '1': return 1; case '2': return 2;
	case '3': return 3; case '4': return 4; case '5': return 5;
	case '6': return 6; case '7': return 7; case '8': return 8;
	case '9': return 9;  default: return 0;
	}
}
bool pairCompare(const pll firstElof, pll secondElof)
{
	return firstElof.first > secondElof.first;
}
//**Snippetリスト**//
//rep, vin, all, iteLoop, bitSearch, bitList, nod, LIS, digitDP, treeDP, Rerooting//
//gcdlcm, isPrime, eratos, primeFactorize, Npow, combination, divisor, modinv, doubling//
//dfs, bfs, dijkstra, WarshallFloyd, BellmanFord, UnionFind, Kruskal, RMQ, LCA, FordFulkerson//
ll i, j, k, l; ll N, M, K, H, W, L, X, Y, Z, R, Q;
ll MOD = 1000000007, INF = 1LL << 60, ans = 0, z = 0, o = 1;
vl flag, D; vll path; vll A;
//***********//
//main内でCOMinit(N+1)を忘れずに！
vl fac, finv, inv;
void COMinit(ll N) {
    fac.resize(N);
    finv.resize(N);
    inv.resize(N);
    fac[0] = fac[1] = 1;
    finv[0] = finv[1] = 1;
    inv[1] = 1;
    for (ll i = 2; i < N; i++) {
        fac[i] = fac[i - 1] * i % MOD;
        inv[i] = MOD - inv[MOD % i] * (MOD / i) % MOD;
        finv[i] = finv[i - 1] * inv[i] % MOD;
    }
}
ll COM(ll n, ll k) {
    if (n < k) return 0;
    if (n < 0 || k < 0) return 0;
    return fac[n] * (finv[k] * finv[n - k] % MOD) % MOD;
}
/* Rerooting: 全方位木 DP
    問題ごとに以下を書き換える
    - 型DPと単位元
    - 型DPに対する二項演算 merge
    - まとめたDPを用いて新たな部分木のDPを計算する add_root
    計算量: O(N)
*/
struct Rerooting {
    /* start 問題ごとに書き換え */
    struct DP {  // DP の型
        ll dp;
        ll s;
        DP(ll dp_, ll s_) : dp(dp_),s(s_) {}
    };
    const DP identity = DP(1,0);  // 単位元(末端の値は add_root(identity) になるので注意)
    function<DP(DP, DP,ll)> merge = [](DP dp_cum, DP d,ll cost) -> DP {
        ll n = dp_cum.s + d.s;
        return DP(((dp_cum.dp*d.dp)%MOD*COM(n,d.s))%MOD,n);
    };
    function<DP(DP)> add_root = [](DP d) -> DP {
        return DP(d.dp,d.s+1);
    };
    /* end 問題ごとに書き換え */
    // グラフの定義
    struct Edge {
        ll from; ll to; ll 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(ll N) : G(N) {
        dp.resize(N);
        ans.assign(N, identity);
    }
    void add_edge(ll a, ll b,ll c=1) {
        G[a].push_back({ a,b,c });
    }
    void build() {
        dfs(0);            // 普通に木DP
        bfs(0, identity);  // 残りの部分木に対応するDPを計算
    }
    DP dfs(ll v, ll p = -1) {  // 頂点v, 親p
        DP dp_cum = identity;
        ll deg = G[v].size();
        dp[v] = vector<DP>(deg, identity);
        for (ll i = 0; i < deg; i++) {
            ll u = G[v][i].to;
            if (u == p) continue;
            dp[v][i] = dfs(u, v);
            dp_cum = merge(dp_cum, dp[v][i],G[v][i].cost);
        }
        return add_root(dp_cum);
    }
    void bfs(ll v, const DP& dp_p, ll p = -1) {  // bfs だが、実装が楽なので中身は dfs になっている
        ll deg = G[v].size();
        for (ll i = 0; i < deg; i++) {  // 前のbfsで計算した有向辺に対応する部分木のDPを保存
            if (G[v][i].to == p) dp[v][i] = dp_p;
        }
        vector<DP> dp_l(deg + 1, identity), dp_r(deg + 1, identity);  // 累積merge
        for (ll i = 0; i < deg; i++) {
            dp_l[i + 1] = merge(dp_l[i], dp[v][i],G[v][i].cost);
        }
        for (ll i = deg - 1; i >= 0; i--) {
            dp_r[i] = merge(dp_r[i + 1], dp[v][i],G[v][i].cost);
        }

        ans[v] = add_root(dp_l[deg]);  // 頂点 v の答え

        for (ll i = 0; i < deg; i++) {  // 一つ隣の頂点に対しても同様に計算
            ll u = G[v][i].to;
            if (u == p) continue;
            bfs(u, add_root(merge(dp_l[i], dp_r[i + 1],0)), v);
        }
    }
};
int main() {
    cin >> N;
    COMinit(N + 1);
    Rerooting reroot(N);
    for (i = 0; i < N - 1; i++) {
        ll u, v;
        cin >> u >> v;
        u--, v--;
        reroot.add_edge(u, v);
        reroot.add_edge(v, u);
    }
    reroot.build();
    for (k = 0; k < N; k++) co(reroot.ans[k].dp);
}

Measured memory_bytes: 46896