Problem:
Score : 600 points

Problem Statement

We have a tree with N vertices numbered 1 to N. The i-th edge in this tree connects Vertex a_i and b_i.
For each k=1, ..., N, solve the problem below:

Consider writing a number on each vertex in the tree in the following manner:

First, write 1 on Vertex k.

Then, for each of the numbers 2, ..., N in this order, write the number on the vertex chosen as follows:

Choose a vertex that still does not have a number written on it and is adjacent to a vertex with a number already written on it. If there are multiple such vertices, choose one of them at random.

Find the number of ways in which we can write the numbers on the vertices, modulo (10^9+7).

Constraints

2 \leq N \leq 2 \times 10^5

1 \leq a_i,b_i \leq N

The given graph is a tree.

Input

Input is given from Standard Input in the following format:

N
a_1 b_1
:
a_{N-1} b_{N-1}

Output

For each k=1, 2, ..., N in this order, print a line containing the answer to the problem.

Sample Input 1

3
1 2
1 3

Sample Output 1

2
1
1

The graph in this input is as follows:

For k=1, there are two ways in which we can write the numbers on the vertices, as follows:

Writing 1, 2, 3 on Vertex 1, 2, 3, respectively

Writing 1, 3, 2 on Vertex 1, 2, 3, respectively

Sample Input 2

2
1 2

Sample Output 2

1
1

The graph in this input is as follows:

Sample Input 3

5
1 2
2 3
3 4
3 5

Sample Output 3

2
8
12
3
3

The graph in this input is as follows:

Sample Input 4

8
1 2
2 3
3 4
3 5
3 6
6 7
6 8

Sample Output 4

40
280
840
120
120
504
72
72

The graph in this input is as follows:

Solution in C++14 (GCC 5.4.1) (judge verdict: Accepted)

/* #region Head */

#include <bits/stdc++.h>
using namespace std;

using ll = long long;
using ull = unsigned long long;
using ld = long double;
using pll = pair<ll, ll>;
template <class T> using vc = vector<T>;
template <class T> using vvc = vc<vc<T>>;
using vll = vc<ll>;
using vvll = vvc<ll>;
using vld = vc<ld>;
using vvld = vvc<ld>;
using vs = vc<string>;
using vvs = vvc<string>;
template <class T, class U> using um = unordered_map<T, U>;
template <class T> using pq = priority_queue<T>;
template <class T> using pqa = priority_queue<T, vc<T>, greater<T>>;

#define REP(i, m, n) for (ll i = (m), i##_len = (ll)(n); i < i##_len; ++(i))
#define REPM(i, m, n) for (ll i = (m), i##_max = (ll)(n); i <= i##_max; ++(i))
#define REPR(i, m, n) for (ll i = (m), i##_min = (ll)(n); i >= i##_min; --(i))
#define REPD(i, m, n, d) for (ll i = (m), i##_len = (ll)(n); i < i##_len; i += (d))
#define REPMD(i, m, n, d) for (ll i = (m), i##_max = (ll)(n); i <= i##_max; i += (d))
#define REPI(itr, ds) for (auto itr = ds.begin(); itr != ds.end(); itr++)
#define ALL(x) begin(x), end(x)
#define SIZE(x) ((ll)(x).size())
#define PERM(c)                                                                                                        \
    sort(ALL(c));                                                                                                      \
    for (bool c##p = 1; c##p; c##p = next_permutation(ALL(c)))
#define UNIQ(v) v.erase(unique(ALL(v)), v.end());

#define endl '\n'
#define sqrt sqrtl
#define floor floorl
#define log2 log2l

constexpr ll INF = 1'010'000'000'000'000'017LL;
constexpr ll MOD = 1'000'000'007LL; // 1e9 + 7
constexpr ld EPS = 1e-12;
constexpr ld PI = 3.14159265358979323846;

template <typename T> istream &operator>>(istream &is, vc<T> &vec) { // vector 入力
    for (T &x : vec) is >> x;
    return is;
}
template <typename T> ostream &operator<<(ostream &os, vc<T> &vec) { // vector 出力 (for dump)
    os << "{";
    REP(i, 0, SIZE(vec)) os << vec[i] << (i == i_len - 1 ? "" : ", ");
    os << "}";
    return os;
}
template <typename T> ostream &operator>>(ostream &os, vc<T> &vec) { // vector 出力 (inline)
    REP(i, 0, SIZE(vec)) os << vec[i] << (i == i_len - 1 ? "\n" : " ");
    return os;
}

template <typename T, typename U> istream &operator>>(istream &is, pair<T, U> &pair_var) { // pair 入力
    is >> pair_var.first >> pair_var.second;
    return is;
}
template <typename T, typename U> ostream &operator<<(ostream &os, pair<T, U> &pair_var) { // pair 出力
    os << "(" << pair_var.first << ", " << pair_var.second << ")";
    return os;
}

// map, um, set 出力
template <class T> ostream out_iter(ostream &os, T &map_var) {
    os << "{";
    REPI(itr, map_var) {
        os << *itr;
        auto itrcp = itr;
        if (++itrcp != map_var.end()) os << ", ";
    }
    os << "}";
    return os;
}
template <typename T, typename U> ostream &operator<<(ostream &os, map<T, U> &map_var) { return out_iter(os, map_var); }
template <typename T, typename U> ostream &operator<<(ostream &os, um<T, U> &map_var) { return out_iter(os, map_var); }
template <typename T> ostream &operator<<(ostream &os, set<T> &set_var) { return out_iter(os, set_var); }

// dump
#define DUMPOUT cerr
void dump_func() { DUMPOUT << endl; }
template <class Head, class... Tail> void dump_func(Head &&head, Tail &&... tail) {
    DUMPOUT << head;
    if (sizeof...(Tail) > 0) DUMPOUT << ", ";
    dump_func(move(tail)...);
}

// chmax (更新「される」かもしれない値が前)
template <typename T, typename U, typename Comp = less<>> bool chmax(T &xmax, const U &x, Comp comp = {}) {
    if (comp(xmax, x)) {
        xmax = x;
        return true;
    }
    return false;
}

// chmin (更新「される」かもしれない値が前)
template <typename T, typename U, typename Comp = less<>> bool chmin(T &xmin, const U &x, Comp comp = {}) {
    if (comp(x, xmin)) {
        xmin = x;
        return true;
    }
    return false;
}

// ローカル用
#define DEBUG_

#ifdef DEBUG_
#define DEB
#define dump(...)                                                                                                      \
    DUMPOUT << "  " << string(#__VA_ARGS__) << ": "                                                                    \
            << "[" << to_string(__LINE__) << ":" << __FUNCTION__ << "]" << endl                                        \
            << "    ",                                                                                                 \
        dump_func(__VA_ARGS__)
#else
#define DEB if (false)
#define dump(...)
#endif

struct AtCoderInitialize {
    static constexpr int IOS_PREC = 15;
    static constexpr bool AUTOFLUSH = false;
    AtCoderInitialize() {
        ios_base::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
        cout << fixed << setprecision(IOS_PREC);
        if (AUTOFLUSH) cout << unitbuf;
    }
} ATCODER_INITIALIZE;

string yes = "Yes", no = "No";
// string yes = "YES", no = "NO";

/* #endregion */

/* #region Lib */

struct mint {
    ll x;
    mint(ll x = 0) : x((x % MOD + MOD) % MOD) {}
    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 {
        mint res(*this);
        return res += a;
    }
    mint operator-(const mint a) const {
        mint res(*this);
        return res -= a;
    }
    mint operator*(const mint a) const {
        mint res(*this);
        return res *= a;
    }
    // O(log(t))
    mint pow(ll t) const {
        if (!t) return 1;
        mint a = pow(t >> 1); // ⌊t/2⌋ 乗
        a *= a;               // ⌊t/2⌋*2 乗
        if (t & 1)            // ⌊t/2⌋*2 == t-1 のとき
            a *= *this;       // ⌊t/2⌋*2+1 乗 => t 乗
        return a;
    }

    // for prime mod
    mint inv() const {
        return pow(MOD - 2); // オイラーの定理から， x^(-1) ≡ x^(p-2)
    }
    mint &operator/=(const mint a) { return (*this) *= a.inv(); }
    mint operator/(const mint a) const {
        mint res(*this);
        return res /= a;
    }
    bool operator==(const mint a) const { return this->x == a.x; }
    bool operator==(const ll a) const { return this->x == a; }

    // mint 入力
    friend istream &operator>>(istream &is, mint &x) {
        is >> x.x;
        return is;
    }

    // mint 出力
    friend ostream &operator<<(ostream &os, mint x) {
        os << x.x;
        return os;
    }
};

template <class T> class ReRooting {
  public:
    int n; // node cnt

  private:
    vc<vc<int>> adjs, idxForAdjs; // adjacents
    vc<T> res;
    vc<vc<T>> dp;
    T ti; // identity
    function<T(T, T)> merge;
    function<T(T, int)> addNode;

  public:
    ReRooting(int n, vc<vc<int>> edges, T ti, function<T(T, T)> merge, function<T(T, int)> addNode)
        : n(n), ti(ti), merge(merge), addNode(addNode), adjs(n), idxForAdjs(n), dp(n), res(n) {
        for (vc<int> &edge : edges) {
            idxForAdjs[edge[0]].push_back(SIZE(adjs[edge[1]]));
            idxForAdjs[edge[1]].push_back(SIZE(adjs[edge[0]]));
            adjs[edge[0]].push_back(edge[1]);
            adjs[edge[1]].push_back(edge[0]);
        }
        REP(i, 0, SIZE(adjs)) dp[i].resize(SIZE(adjs[i]));
        if (n > 1)
            init();
        else if (n == 1)
            res[0] = addNode(ti, 0);
    }

    T query(int node) { return res[node]; }

  private:
    void init() {
        vc<int> parents(n);
        vc<int> order(n);

        { // 行きがけ順の記録
            int index = 0;
            stack<int> stack;
            stack.push(0);
            parents[0] = -1;
            while (stack.size() > 0) {
                int node = stack.top();
                stack.pop();
                order[index++] = node;
                for (int adjacent : adjs[node]) {
                    if (adjacent == parents[node]) continue;
                    stack.push(adjacent);
                    parents[adjacent] = node;
                }
            }
        }

        { // 帰りがけ順で部分木の値を求めていく
            REPR(i, SIZE(order) - 1, 1) {
                int node = order[i], parent = parents[node];

                T accum = ti;
                int parentIndex = -1;
                REP(j, 0, SIZE(adjs[node])) {
                    if (adjs[node][j] == parent)
                        parentIndex = j;
                    else
                        accum = merge(accum, dp[node][j]);
                }
                dp[parent][idxForAdjs[node][parentIndex]] = addNode(accum, node);
            }
        }

        // 行きがけ順で頂点の値を確定させていく
        for (int node : order) {
            int sz = SIZE(adjs[node]);
            T accum = ti;
            vc<T> accumsFromTail(sz);
            accumsFromTail[sz - 1] = ti;
            REPR(j, sz - 1, 1) accumsFromTail[j - 1] = merge(dp[node][j], accumsFromTail[j]);
            REP(j, 0, sz) {
                dp[adjs[node][j]][idxForAdjs[node][j]] = addNode(merge(accum, accumsFromTail[j]), node);
                accum = merge(accum, dp[node][j]);
            }
            res[node] = addNode(accum, node);
        }
    } // end init
};

// 二項係数計算用クラス．1 <= k <= n <= 1e7 程度用．
class Combinaion {
  private:
    /* テーブルの大きさの既定値．(MAX)! まで計算できる． */
    static constexpr ll MAX = 1e6 + 11;
    /* 実際のテーブルの大きさ． */
    ll max;
    /* 階乗を格納するテーブル．fac[n] := n! % MOD. */
    vc<mint> fac;
    /* 階乗の逆元を格納するテーブル．finv[n] := (fac[n])^(-1). */
    vc<mint> finv;

    /* 各種テーブルを初期化する． */
    void init(int n) {
        max = n;
        fac[0] = fac[1] = 1;
        finv[0] = finv[1] = 1;
        REPM(i, 2, n) { fac[i] = fac[i - 1] * i; }
        finv[n] = fac[n].inv();
        REPR(i, n, 2) { finv[i - 1] = finv[i] * i; }
    }

  public:
    /* コンストラクタ． */
    Combinaion(int n = MAX) : fac(n + 1), finv(n + 1) { init(n); }

    /* 二項係数 nCk % MOD を計算する． */
    mint operator()(ll n, ll k) const {
        assert(n <= max); // ここで詰まると RE
        assert(k <= max);
        if (n < k || n < 0 || k < 0) return 0;
        return fac[n] * finv[k] * finv[n - k];
    }

    mint perm(ll n, ll k) { return fac[n] * finv[n - k]; }

    // 重複組み合わせ nHr % MOD を計算する
    mint homogeneous(ll n, ll r) { return (*this)(n + r - 1, r); }
};

/* #endregion */

// Problem
void solve() {
    int n;
    cin >> n;
    vc<int> a(n - 1), b(n - 1);
    REP(i, 0, n - 1) cin >> a[i] >> b[i];

    vc<vc<int>> edges(n - 1, vc<int>(2));
    REP(i, 0, n - 1) edges[i][0] = --a[i], edges[i][1] = --b[i];

    using T = pair<int, mint>; // nodeCnt, patCnt
    Combinaion c;
    auto merge = [&c](T s, T t) {
        mint comb = c(s.first + t.first, s.first);
        comb *= s.second;
        comb *= t.second;
        return make_pair(s.first + t.first, comb);
    };
    auto addNode = [](T val, int id) { return make_pair(val.first + 1, val.second); };
    ReRooting<T> rr(n, edges, make_pair(0, mint(1)), merge, addNode);

    REP(i, 0, n) cout << rr.query(i).second << endl;
}

// entry point
int main() {
    solve();
    return 0;
}