//
//  main.cpp
//

#include <algorithm>
#include <array>
#include <assert.h>
#include <complex>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <math.h>
#include <memory>
#include <memory>
#include <queue>
#include <random>
#include <set>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <vector>

using namespace std;

using ll = int64_t;
using ull = uint64_t;
constexpr ll LL_MAX = numeric_limits<ll>::max();
constexpr ull ULL_MAX = numeric_limits<ull>::max();

template<typename T>
vector<T> make_vec_nd(T init, ll size) {
	return vector<T>(size, init);
}
template<typename T, typename... Args>
auto make_vec_nd(T init, ll size, Args... rest) {
	auto inner = make_vec_nd(init, rest...);
	return vector<decltype(inner)>(size, inner);
}

#define rep(i, a, b) for (ll i = (a); i < (b); i++)
#define rrep(i, a, b) for (ll i = (a)-1; i >= (b); i--)

struct Mod {
    static uint64_t PRIME;
    struct LocalPrime {
        uint64_t backup;
        LocalPrime(uint64_t prime) { backup = exchange(Mod::PRIME, prime); }
        ~LocalPrime() { Mod::PRIME = backup; }
    };
    uint64_t value = 0;
    Mod()
    : value(0) {}
    Mod(ll v) {
        if (v >= 0) {
            value = v % PRIME;
        } else {
            value = PRIME - (-v) % PRIME;
        }
    }
    Mod operator+(const Mod& rhs) const { return Mod(*this) += rhs; }
    Mod& operator+=(const Mod& rhs) {
        value += rhs.value;
        if (value >= PRIME) {
            value -= PRIME;
        }
        return *this;
    }
    Mod operator-(const Mod& rhs) const { return Mod(*this) -= rhs; }
    Mod& operator-=(const Mod& rhs) {
        if (value < rhs.value) {
            value += PRIME;
        }
        value -= rhs.value;
        return *this;
    }
    Mod operator*(const Mod& rhs) const { return Mod(*this) *= rhs; }
    Mod& operator*=(const Mod& rhs) {
        value = (value * rhs.value) % PRIME;
        return *this;
    }
    Mod inv() const { return power(*this, PRIME - 2); }
    Mod operator/(const Mod& rhs) const { return Mod(*this) /= rhs; }
    Mod& operator/=(const Mod& rhs) {
        *this *= rhs.inv();
        return *this;
    }
    static Mod power(Mod rhs, ll exp) {
        Mod ans = 1;
        while (exp > 0) {
            if (exp % 2) {
                ans *= rhs;
            }
            rhs *= rhs;
            exp /= 2;
        }
        return ans;
    }
};
uint64_t Mod::PRIME = 1000000007;

struct Node {
    ll idx = -1;
    ll parent = -1;
    vector<ll> children;
    unordered_map<ll, ll> idx_in_children;
};

template<typename M>
// Rerooting (全方位木dp)
// M: 可換モノイド（operator+, デフォルトコンストラクタを要求）
// 木tree、辺(from, to)に対し、
// subtree(tree, from, to) := fromからtoへ向かう辺を除去して得られるtoを根とする部分木
// とする。
// 根付き木tree（根はroot）に対する値 f(tree) in M であって、
// f(tree) = augment + \sum_{v} f(subtree(tree, root, v))
// となるようなものを考える。
// 与えられたtreeに対し、
// ・全ての頂点vに対するf((tree, v))
// ・全ての辺(from, to)に対するf(subtree(tree, from, to))
// をO(N)で求める
struct Rerooting {
    vector<ll> parent;
    // fold_except[from][to] =
    // それぞれに対する答えをv!=toに対して計算して、モノイド演算で畳み込んだもの
    // to=-1のときは全てのvに対する答えを畳み込んだもの
    vector<unordered_map<ll, M>> fold_except;
    // 辺(from, to)において、f(subtree(tree, from, to))を求める際に、subtreeに対する
	// 結果を畳み込んだ後に最終的な結果を得るために通す関数 augment(from, to, x)。
    // 例えばf(tree)=頂点数のときは、augment(from, to, x) = x+1
	// from = -1となることがあるので注意
    function<M(ll, ll, M)> augment;
    
    Rerooting(const vector<vector<ll>>& tree, function<M(ll,ll,M)> augment) : augment(augment) {
        parent.resize(tree.size(), -2); // calc_downでのvisitフラグ兼用
        parent[0] = -1;
        fold_except.resize(tree.size());
        calc_down(0, tree); // 子方向に伸びるsubtreeだけを考慮してfold_exceptを計算
        calc_up(0, tree); // さらに親方向に伸びるsubtreeの結果もfold_exceptに畳み込んで、完成
    }
    void calc_down(ll root, const vector<vector<ll>>& tree) {
        const vector<ll>& edges = tree[root];
        vector<pair<ll, M>> elems; // (to, result)
        elems.reserve(edges.size());
        for (ll i = 0; i < edges.size(); i++) {
            ll to = edges[i];
            if (parent[to] >= -1) {
                continue;
            }
            parent[to] = root;
            calc_down(to, tree);
            elems.push_back(make_pair(to, augment(root, to, fold_except[to][root])));
        }
        vector<M> foldr(elems.size()+1);
        for (ll i = (ll)elems.size() - 1; i >= 0; i--) {
            foldr[i] = elems[i].second + foldr[i+1];
        }
        fold_except[root].reserve(elems.size());
        M foldl = {};
        for (ll i = 0; i < elems.size(); i++) {
            fold_except[root][elems[i].first] = foldl + foldr[i+1];
            foldl = elems[i].second + foldl;
        }
        fold_except[root][parent[root]] = foldl;
    }
    void calc_up(ll root, const vector<vector<ll>>& tree) {
        const vector<ll>& edges = tree[root];
        M par = {};
        if (root != 0) {
            par = augment(root, parent[root], fold_except[parent[root]][root]);
        }
        for (ll to : edges) {
            if (to != parent[root]) {
                fold_except[root][to] = fold_except[root][to] + par;
            }
        }
        fold_except[root][-1] = fold_except[root][parent[root]] + par;
        for (ll to : edges) {
            if (to != parent[root]) {
                calc_up(to, tree);
            }
        }
    }
    M query(ll root) {
        return augment(-1, root, fold_except[root][-1]);
    }
    M query_subtree(ll from, ll to) {
        return augment(from, to, fold_except[to][from]);
    }
};

vector<Mod> fact;
vector<Mod> facti;

int main() {
    ll N;
    cin >> N;
    fact.resize(N+1, 1);
    facti.resize(N+1, 1);
    rep(n,1,N+1) {
    	fact[n] = fact[n-1] * n;
    	facti[n] = facti[n-1] / n;
    }
    vector<vector<ll>> tree(N);
    rep(i,0,N-1) {
        ll a, b;
        cin >> a >> b;
        a--;
        b--;
        tree[a].push_back(b);
        tree[b].push_back(a);
    }
    Rerooting<ll> cnt(tree, [](ll from, ll to, ll x){ return x+1; });
    vector<Mod> binom_denom(N);
    rep(from,0,N) {
    	binom_denom[from] = 1;
    	for (ll to : tree[from]) {
    		binom_denom[from] *= fact[cnt.query_subtree(from, to)];
    	}
    }
    struct Mult {
    	Mod data = 1;
    	Mult operator+(const Mult& rhs) {
    		return Mult{ data * rhs.data };
    	}
    };
    Rerooting<Mult> ans(tree, [&binom_denom, &cnt, N](ll from, ll to, Mult x) {
		Mod data = binom_denom[to];
		ll numer = N-1;
		if (from != -1) {
			data *= facti[cnt.query_subtree(to, from)];
			numer -= cnt.query_subtree(to, from);
		}
		data = fact[numer] / data;
    	return Mult { 
			data * x.data
		};
    });
    rep(i,0,N) {
//    	cout << binom[i].value << endl;
		cout << ans.query(i).data.value << endl;
    }
}


Measured memory_bytes: 115200