#include <iostream>
#include <algorithm>
#include <iomanip>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <vector>
#include <string>
#include <queue>
#include <deque>
#include <list>
#include <set>
#include <unordered_set>
#include <map>
#include <unordered_map>
#include <bitset>
#include <random>
#include <complex>
#include <assert.h>

using namespace std;
typedef long long ll;

#define endl '\n'

template<typename T>
inline bool chmin(T& x, T a) {
	if (x >= a) { x = a; return true; }
	return false;
}

template<typename T>
inline bool chmax(T& x, T a) {
	if (x <= a) { x = a; return true; }
	return false;
}

/////////////         modの計算

#define MOD_IS_PRIME
const ll mod = 1000000007LL;

class modlong {
public:
	modlong() {
		x = 0;
	}
	modlong(ll num) {
		x = adjust(num);
	}
	inline operator ll() const {
		return x;
	}
	inline bool operator ==(ll num) {
		return this->x == num;
	}
	inline bool operator !=(ll num) {
		return !(*this == num);
	}
	inline void operator = (ll num) {
		x = adjust(num);
	}
	inline void operator += (ll num) {
		x = adjust(x + num);
	}
	inline void operator ++() {
		this->operator+=(1);
	}
	inline modlong operator + (ll num) const {
		modlong m(this->x);
		m += num;
		return m;
	}
	inline void operator -= (ll num) {
		x = adjust(x - num);
	}
	inline void operator --() {
		this->operator-=(1);
	}
	inline modlong operator - (ll num) {
		modlong m(this->x);
		m -= num;
		return m;
	}
	inline void operator *= (ll num) {
		x = adjust(x * num);
	}
	inline modlong operator * (ll num) {
		modlong m(this->x);
		m *= num;
		return m;
	}
	inline void operator /=(ll num);
	inline modlong operator /(ll num);
private:
	inline ll adjust(ll a) {
		if (a >= mod) {
			return a % mod;
		}
		if (a < 0) {
			return mod - 1 + ((a + 1) % mod);
		}
		return a;
	}
	ll x;
};

inline modlong mod_inv(modlong a) {
	const ll inv_max = 300000;
	static vector<ll> inv;
	ll k = a;
	assert(k > 0);

	if (k <= inv_max) {
		ll M = inv.size();
		if (M <= k) {
			if (M == 0) { inv.push_back(0); M++; }
			if (M == 1) { inv.push_back(1); M++; }

			for (ll i = M; i <= k; i++) {
				ll p = mod / i;
				ll q = mod - (p * i);
				inv.push_back(((mod - p) * inv[q]) % mod);
			}
		}
		return inv[k];
	}

	ll p = mod, q = k;
	modlong m = 0, n = 1, r, c;

	ll s = inv.size();
	while (q > 1) {
		if (q < s) {
			return n * inv[q];
		}
		c = p / q;
		r = p - (q * c);
		c = m - n * c;
		p = q, m = n, q = r, n = c;
	}
	return n;
}
inline modlong mod_div(modlong a, modlong b) {
	return a * mod_inv(b);
}
inline void modlong::operator /=(ll num) {
	x = mod_div(*this, num);
}
inline modlong modlong::operator /(ll num) {
	modlong m(this->x);
	m /= num;
	return m;
}

inline modlong mod_pow(modlong x, ll n) {
	if (n < 0) {
		x = mod_inv(x);
		n = -n;
	}

#ifdef MOD_IS_PRIME
	n = n % (mod - 1);
#endif

	modlong temp = x, ans = 1;
	while (n > 0) {
		if (n & 1) {
			ans *= temp;
		}
		temp *= temp;
		n >>= 1;
	}
	return ans;
}
inline modlong mod_log(modlong a, modlong x) {
	ll A = sqrt(mod);
	ll B = (mod + A - 1) / A;
	map<ll, ll> mp1, mp2;
	ll p0 = a;
	ll q0 = mod_pow(a, -A);
	ll p = 1;
	ll q = x;
	for (int i = 0; i < A; i++) {
		mp1.insert({ p, i });
		p = (p * p0) % mod;
	}
	for (int i = 0; i < B; i++) {
		mp2.insert({ q, A * i });
		q = (q * q0) % mod;
	}
	auto itr1 = mp1.begin();
	auto itr2 = mp2.begin();
	while (itr1 != mp1.end() && itr2 != mp2.end()) {
		if (itr1->first < itr2->first) {
			itr1++;
		}
		else if (itr1->first == itr2->first) {
			return itr1->second + itr2->second;
		}
		else {
			itr2++;
		}
	}
	return 0;
}

inline modlong mod_factorial(modlong n, bool inverse = false) {
	static vector<ll> factorial, factorial_inv;

	ll M = factorial.size();
	if (M <= n) {
		if (M == 0) { factorial.push_back(1); factorial_inv.push_back(1); M++; }
		if (M == 1) { factorial.push_back(1); factorial_inv.push_back(1); M++; }

		for (ll i = M; i <= n; i++) {
			factorial.push_back((factorial.back() * i) % mod);
			factorial_inv.push_back((factorial_inv.back() * mod_inv(i)) % mod);
		}
	}
	if (inverse == true) {
		return factorial_inv[n];
	}
	else {
		return factorial[n];
	}
}
inline modlong mod_combination(modlong n, modlong r) {
	assert(r <= n);
	return mod_factorial(n) * mod_factorial(n - r, true) * mod_factorial(r, true);
}

///////////////// 各種設定 /////////////////

#define USE_SUBTREE_SIZE
// #define USE_LCA

class TreeClass {// 木の入力を受け取る
public:
	TreeClass() {
		N = 0, root = 0;
		next = NULL;
#ifdef USE_LCA
		parent = NULL;
#endif
	}
	TreeClass(int _N, int _root = 0) {
		next = NULL;
#ifdef USE_LCA
		parent = NULL;
#endif
		activate(_N, _root);
	}

	~TreeClass() {
		if (next != NULL) { delete[] next; }
#ifdef USE_LCA
		if (parent != NULL) { delete[] parent; }
#endif
	}

	void activate(int n, int _root = 0) {// 頂点数nのグラフを初期化する。
		N = n;
		root = _root;

		weight.resize(N);
		for (int i = 0; i < N; i++) { weight[i] = 1; }

		back.resize(N);
		if (next != NULL) { delete[] next; }
		next = new unordered_map<int, int>[N];
		edge.clear();

		depth.clear();
		depth.resize(N);

#ifdef USE_SUBTREE_SIZE
		subtree_size.clear();
		subtree_size.resize(N);
#endif
#ifdef USE_LCA
		if (parent != NULL) { delete[] parent; }
		parent = new vector<int>[N];
		for (int i = 0; i < N; i++) { parent[i].clear(); }
#endif
	}
	inline void setNodeWeight(int n, ll weight) {// n番のノードの重みをweightに設定
		this->weight[n] = weight;
	}

	inline int getEdgeIndex(int x, int y) {// 辺の組からエッジの番号を得る
		if (next[x].find(y) != next[x].end()) {
			return next[x][y];
		}
		return -1;
	}
	inline void addEdge(int x, int y, ll _weight = 1) {// エッジ追加
		int M = (int)edge.size();
		edge.push_back({ {x,y}, _weight });

		next[x].insert({ y, M });
		next[y].insert({ x, M });

		if (edge.size() == N - 1) {
			initProcess();

#ifdef USE_SUBTREE_SIZE
			dfs(&TreeClass::dfs_processSubtreeSize);
#endif
#ifdef USE_LCA
			bfs(&TreeClass::bfs_processDoubling);
#endif
		}
	}

#ifdef USE_LCA
	inline int LCA(int a, int b) {
		int d = min(depth[a], depth[b]);

		if (depth[a] > d) {
			int k = depth[a] - d;
			for (int i = 0; k > 0; i++) {
				if ((1 << i) & k) {
					k -= (1 << i);
					a = parent[a][i];
				}
			}
		}
		if (depth[b] > d) {
			int k = depth[b] - d;
			for (int i = 0; k > 0; i++) {
				if ((1 << i) & k) {
					k -= (1 << i);
					b = parent[b][i];
				}
			}
		}
		if (a == b) { return a; }

		for (int k = parent[a].size() - 1; k >= 0; k--) {
			if (k < parent[a].size() && k < parent[b].size() && (parent[a][k] != parent[b][k])) {
				a = parent[a][k];
				b = parent[b][k];
			}
		}
		return parent[a][0];
	}
#endif

	inline void changeRoot(int r, bool ProcessDoublingFlag = true) {
		assert(r >= 0 && r < N);
		root = r;
		initProcess();

#ifdef USE_SUBTREE_SIZE
		dfs(&TreeClass::dfs_processSubtreeSize);
#endif
#ifdef USE_LCA
		if (ProcessDoublingFlag)  bfs(&TreeClass::bfs_processDoubling);
#endif
	}

	inline pair<int, vector<int>> getDiameter_and_Center() {
		int r0 = root;
		int d1 = -1, k1 = -1;
		for (int i = 0; i < N; i++) {
			if (chmax(d1, depth[i])) {
				k1 = i;
			}
		}
		changeRoot(k1, false);

		int d2 = -1, k2 = -1;
		for (int i = 0; i < N; i++) {
			if (chmax(d2, depth[i])) {
				k2 = i;
			}
		}
		int i = k2;
		if (d2 % 2 == 0) {
			while (1) {
				int j = back[i].first;
				if (depth[j] == d2 / 2) {
					changeRoot(r0, false);
					return { d2, { j } };
				}
				i = j;
			}
		}
		else {
			while (1) {
				int j = back[i].first;
				if (depth[j] == d2 / 2) {
					changeRoot(r0, false);
					return { d2, { i, j } };
				}
				i = j;
			}
		}
		return { d2, { root } };
	}
private:
	inline void initProcess() {// bfsの順番を取得すると同時に、根からの深さを得る。
		for (int i = 0; i < N; i++) {
			depth[i] = -1;
			back[i] = { -1, -1 };
		}

		queue<pair<int, int>> q; q.push({ root, 0 });

		bfs_order.clear();

		while (q.size() > 0) {
			int n = q.front().first;
			int d = q.front().second;
			q.pop();

			bfs_order.push_back(n);

			depth[n] = d;

			auto _erase = next[n].end();// 根に向かう辺
			for (auto itr = next[n].begin(); itr != next[n].end(); itr++) {
				int m = itr->first;

				if (depth[m] == -1) {
					q.push({ m, d + 1 });
				}
				else {
					_erase = itr;
					back[n] = { itr->first, itr->second };
				}
			}
			if (_erase != next[n].end()) {
				next[n].erase(_erase);
			}
		}
	}
	inline void dfs(void (TreeClass::* dfs_process)(int n)) {
		for (int i = N - 1; i >= 0; i--) {
			(this->*dfs_process)(bfs_order[i]);
		}
	}
	inline void bfs(void (TreeClass::* bfs_process)(int n)) {
		for (int i = 0; i < N; i++) {
			(this->*bfs_process)(bfs_order[i]);
		}
	}

#ifdef USE_SUBTREE_SIZE
	void dfs_processSubtreeSize(int n) {// 部分木のサイズを得る
		subtree_size[n] = 1;
		for (auto itr = next[n].begin(); itr != next[n].end(); itr++) {
			subtree_size[n] += subtree_size[itr->first];
		}
	}
#endif
#ifdef USE_LCA
	void bfs_processDoubling(int n) {// ダブリング
		parent[n].clear();
		if (n == root) { return; }

		parent[n].push_back(back[n].first);
		for (int k = 0; depth[n] >= (1 << (k + 1)); k++) {
			parent[n].push_back(parent[parent[n][k]][k]);
		}
	}
#endif

public:
	int N, root;
	vector<ll> weight;// ノードの重み

	vector<pair<pair<int, int>, ll>> edge;// エッジ(頂点ペアと重み)

	vector<pair<int, int>> back;// 根に近いノードと、エッジ番号
	unordered_map<int, int>* next;// 各ノードからの行き先とエッジ番号

	vector<int> depth;// 根から見た深さ
	vector<int> bfs_order;// bfsの際に訪れる順番(dfsは逆順)

#ifdef USE_SUBTREE_SIZE
	vector<int> subtree_size;// 部分木のサイズ
#endif
#ifdef USE_LCA
	vector<int>* parent;//1番目、2番目、4番目、8番目...の親
#endif
};

inline void dfs(TreeClass &T, void (*dfs_process)(TreeClass& T, int n)) {
	for (int i = T.N - 1; i >= 0; i--) {
		dfs_process(T, T.bfs_order[i]);
	}
}
inline void bfs(TreeClass& T, void (*bfs_process)(TreeClass& T, int n)) {
	for (int i = 0; i < T.N; i++) {
		bfs_process(T, T.bfs_order[i]);
	}
}

class TreeDP_data {
public:
	TreeDP_data() {

	}
	void init(TreeClass& T, int _n) {
		n = _n;
		sum = 0;
		forward_ans = 1;
		ans = 1;
	}
	inline void forward_ans_tie(TreeClass& T, TreeDP_data& Other) {
		int m = Other.n;

		////////////以下に処理を書く////////////
		int sizem = T.subtree_size[m];
		forward_ans *= mod_combination(sum + sizem, sum); sum += sizem;
		forward_ans *= Other.forward_ans;
	}
	inline void backward_ans_tie(TreeClass& T, TreeDP_data& Other) {
		int m = Other.n;

		////////////以下に処理を書く////////////
		modlong sizen = T.subtree_size[n];
		ans = Other.ans * sizen / (T.N - sizen);
	}
	
	int n;
	ll sum;
	modlong forward_ans, ans;
};
vector<TreeDP_data> DP_data;

void TreeDP_forwardProcess(TreeClass &T, int n) {
	for (auto itr = T.next[n].begin(); itr != T.next[n].end(); itr++) {
		int m = itr->first;
		DP_data[n].forward_ans_tie(T, DP_data[m]);
	}
}
void TreeDP_backwardProcess(TreeClass& T, int n) {
	if (n == T.root) { DP_data[n].ans = DP_data[n].forward_ans; return; }
	int m = T.back[n].first;
	DP_data[n].backward_ans_tie(T, DP_data[m]);
}
inline void TreeDP(TreeClass &T) {
	DP_data.clear();
	DP_data.resize(T.N);
	for (int i = 0; i < T.N; i++) {
		DP_data[i].init(T, i);
	}
	dfs(T, TreeDP_forwardProcess);
	bfs(T, TreeDP_backwardProcess);
}

int main() {
	ios::sync_with_stdio(false);
	std::cin.tie(0);

	int N; cin >> N;
	TreeClass T(N);

	for (int i = 0; i < N - 1; i++) {
		int a, b; cin >> a >> b;
		a--, b--;
		T.addEdge(a, b);
	}

	TreeDP(T);
	for (int i = 0; i < N; i++) {
		cout << DP_data[i].ans << endl;
	}

	return 0;
}

Measured memory_bytes: 57524