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:



Sample input:
3
1 2
1 3


Sample output:
2
1
1

Submission status: Runtime Error

Solution code:
# -*- coding: utf-8 -*-
"""
Created on Fri May  8 12:10:59 2020

@author: ybt07
"""

import sys
sys.setrecursionlimit(3*10**5)  # 繰り返し制限

# 組み合わせ
N = 2*10**5  # 問題サイズに合わせて変えておく
MOD = 10**9 + 7

# modint
# https://qiita.com/wotsushi/items/c936838df992b706084c

MOD = 10**9 + 7

class ModInt:
    def __init__(self, x):
        self.x = x % MOD

    def __str__(self):
        return str(self.x)

    __repr__ = __str__

    def __add__(self, other):
        return (
            ModInt(self.x + other.x) if isinstance(other, ModInt) else
            ModInt(self.x + other)
        )

    def __sub__(self, other):
        return (
            ModInt(self.x - other.x) if isinstance(other, ModInt) else
            ModInt(self.x - other)
        )

    def __mul__(self, other):
        return (
            ModInt(self.x * other.x) if isinstance(other, ModInt) else
            ModInt(self.x * other)
        )

    # // : 商。　逆元はフェルマーの小定理を利用している
    def __floordiv__(self, other):
        return (
            ModInt(
                self.x * inv[other.x]
            ) if isinstance(other, ModInt) else
            ModInt(self.x * inv[other])
        )

    # ** : 指数
    def __pow__(self, other):
        return (
            ModInt(pow(self.x, other.x, MOD)) if isinstance(other, ModInt) else
            ModInt(pow(self.x, other, MOD))
        )

    # x が Modint、y が通常の int の場合に、y.__add__(x) に対して、何を適用するか、定義している（→ x.__add__(y)を呼べ） 
    __radd__ = __add__

    def __rsub__(self, other):
        return (
            ModInt(other.x - self.x) if isinstance(other, ModInt) else
            ModInt(other - self.x)
        )

    __rmul__ = __mul__

    def __rtruediv__(self, other):
        return (
            ModInt(
                other.x * pow(self.x, MOD - 2, MOD)
            ) if isinstance(other, ModInt) else
            ModInt(other * pow(self.x, MOD - 2, MOD))
        )

    def __rpow__(self, other):
        return (
            ModInt(pow(other.x, self.x, MOD)) if isinstance(other, ModInt) else
            ModInt(pow(other, self.x, MOD))
        )

def cmb(n, r):
    if ( r<0 or r>n ):
        return 0
    r = min(r, n-r)
    return ModInt(fac[n] * facinv[r] * facinv[n-r])

fac = [1, 1] # 元テーブル
facinv = [1, 1] #逆元テーブル
inv = [0, 1] #逆元テーブル計算用テーブル

for i in range( 2, N + 1 ):
    fac.append( ( fac[-1] * i ) % MOD )
    inv.append( ( -inv[MOD % i] * (MOD//i) ) % MOD )
    facinv.append( (facinv[-1] * inv[-1]) % MOD )

# 部分木のDP値を求めていく
# u : 求める頂点
# 親（親側に辿らないように） p

def dfs(u, p = -1):

    global DP, CN, E
    
    tmp_ans = 1
    tmp_cn = 0  # （自分を含む）部分木のノード数

    # u から出ている頂点 v
    for v in E[u]:
        if v != p:  # 親への辺以外について
            DP[v], CN[v] = dfs(v, u)
            tmp_cn += CN[v]
            tmp_ans *= DP[v] * cmb(tmp_cn, CN[v])
    DP[u] = tmp_ans
    CN[u] = tmp_cn + 1
            
    return DP[u], CN[u]

# 各頂点の真のDP値を求めていく

def bfs(u, p=-1):
    
    global DP, E
    
    tmp_ans = DP[u]
    tmp_cn = 1
    
    for v in E[u]:  # 各vに対して「真のDP値」を求めていく
        if v == p:
            continue
            
        # DP[u] と DP[v] から DP[v <- u] を求める
        tmp_cn = N - CN[v]  # v から見たときの u の部分木の要素数
        # print(v+1,tmp_cn)
        tmp_ans = DP[u] // DP[v] // cmb(N - 1, CN[v])
                
        # DP[u <- v] を使って、DP[v] を更新する
        DP[v] = DP[v] * tmp_ans * cmb(N-1, tmp_cn)
        bfs(v, u)
    
    return

# 入力処理
N = int(input())  # 頂点数
E = [[] for _ in range(N)]  # 辺の情報

for _ in range(N - 1):
    a, b = map(int, input().split())
    E[a-1].append(b-1)  # 双方向の情報
    E[b-1].append(a-1)
    
DP = [ModInt(1)] * N
CN = [0] * N

dfs(0)
bfs(0)

for i in DP:
    print(i)

Submission status: Runtime Error

Solution code:
# -*- coding: utf-8 -*-
"""
Created on Fri May  8 12:10:59 2020

@author: ybt07
"""

import sys
sys.setrecursionlimit(3*10**5)  # 繰り返し制限

# 組み合わせ
N = 2*10**5  # 問題サイズに合わせて変えておく
MOD = 10**9 + 7

# modint
# https://qiita.com/wotsushi/items/c936838df992b706084c

MOD = 10**9 + 7

class ModInt:
    def __init__(self, x):
        self.x = x % MOD

    def __str__(self):
        return str(self.x)

    __repr__ = __str__

    def __add__(self, other):
        return (
            ModInt(self.x + other.x) if isinstance(other, ModInt) else
            ModInt(self.x + other)
        )

    def __sub__(self, other):
        return (
            ModInt(self.x - other.x) if isinstance(other, ModInt) else
            ModInt(self.x - other)
        )

    def __mul__(self, other):
        return (
            ModInt(self.x * other.x) if isinstance(other, ModInt) else
            ModInt(self.x * other)
        )

    # // : 商。　逆元はフェルマーの小定理を利用している
    def __truediv__(self, other):
        return ModInt(self.x * facinv[other.x])

    # ** : 指数
    def __pow__(self, other):
        return (
            ModInt(pow(self.x, other.x, MOD)) if isinstance(other, ModInt) else
            ModInt(pow(self.x, other, MOD))
        )

    # x が Modint、y が通常の int の場合に、y.__add__(x) に対して、何を適用するか、定義している（→ x.__add__(y)を呼べ） 
    __radd__ = __add__

    def __rsub__(self, other):
        return (
            ModInt(other.x - self.x) if isinstance(other, ModInt) else
            ModInt(other - self.x)
        )

    __rmul__ = __mul__

    def __rtruediv__(self, other):
        return (
            ModInt(
                other.x * pow(self.x, MOD - 2, MOD)
            ) if isinstance(other, ModInt) else
            ModInt(other * pow(self.x, MOD - 2, MOD))
        )

    def __rpow__(self, other):
        return (
            ModInt(pow(other.x, self.x, MOD)) if isinstance(other, ModInt) else
            ModInt(pow(other, self.x, MOD))
        )

def cmb(n, r):
    if ( r<0 or r>n ):
        return 0
    r = min(r, n-r)
    return ModInt(fac[n] * facinv[r] * facinv[n-r])

fac = [1, 1] # 元テーブル
facinv = [1, 1] #逆元テーブル
inv = [0, 1] #逆元テーブル計算用テーブル

for i in range( 2, N + 1 ):
    fac.append( ( fac[-1] * i ) % MOD )
    inv.append( ( -inv[MOD % i] * (MOD//i) ) % MOD )
    facinv.append( (facinv[-1] * inv[-1]) % MOD )

# 部分木のDP値を求めていく
# u : 求める頂点
# 親（親側に辿らないように） p

def dfs(u, p = -1):

    global DP, CN, E
    
    tmp_ans = 1
    tmp_cn = 0  # （自分を含む）部分木のノード数

    # u から出ている頂点 v
    for v in E[u]:
        if v != p:  # 親への辺以外について
            DP[v], CN[v] = dfs(v, u)
            tmp_cn += CN[v]
            tmp_ans *= DP[v] * cmb(tmp_cn, CN[v]) % MOD
    
    DP[u] = tmp_ans
    CN[u] = tmp_cn + 1
            
    return DP[u], CN[u]

# 各頂点の真のDP値を求めていく

def bfs(u, p=-1):
    
    global DP, E
    
    tmp_ans = DP[u]
    tmp_cn = 1
    
    for v in E[u]:  # 各vに対して「真のDP値」を求めていく
        if v == p:
            continue
            
        # DP[u] と DP[v] から DP[v <- u] を求める
        tmp_cn = N - CN[v]  # v から見たときの u の部分木の要素数
        # print(v+1,tmp_cn)
        tmp_ans = DP[u] // DP[v] // cmb(N - 1, CN[v])
                
        # DP[u <- v] を使って、DP[v] を更新する
        DP[v] = DP[v] * tmp_ans * cmb(N-1, tmp_cn) % MOD
        bfs(v, u)
    
    return

# 入力処理
N = int(input())  # 頂点数
E = [[] for _ in range(N)]  # 辺の情報

for _ in range(N - 1):
    a, b = map(int, input().split())
    E[a-1].append(b-1)  # 双方向の情報
    E[b-1].append(a-1)
    
DP = [ModInt(1)] * N
CN = [0] * N

dfs(0)
bfs(0)

for i in DP:
    print(i)

Submission status: Runtime Error

Solution code:
from copy import deepcopy as copy
n = int(input())
MOD = 10**9+7
class mint:
    def __init__(self, x):
        self.x = x % MOD if isinstance(x, int) else int(x) % MOD
    def __str__(self):
        return str(self.x)
    __repr__ = __str__
    def __iadd__(self, other):
        self.x += other.x if isinstance(other, mint) else other
        self.x -= MOD if self.x >= MOD else 0
        return self
    def __isub__(self, other):
        self.x += MOD-other.x if isinstance(other, mint) else MOD-other
        self.x -= MOD if self.x >= MOD else 0
        return self
    def __imul__(self, other):
        self.x *= other.x if isinstance(other, mint) else other
        self.x %= MOD
        return self
    def __imod__(self, other):
        self.x %= other.x if isinstance(other, mint) else other
        self.x %= MOD
        return self
    def __add__(self, other):
        return (
            mint(self.x + other.x) if isinstance(other, mint) else
            mint(self.x + other)
        )
    def __sub__(self, other):
        return (
            mint(self.x - other.x) if isinstance(other, mint) else
            mint(self.x - other)
        )
    def __mul__(self, other):
        return (
            mint(self.x * other.x) if isinstance(other, mint) else
            mint(self.x * other)
        )
    def __mod__(self, other):
        return (
            mint(self.x % other.x) if isinstance(other, mint) else
            mint(self.x % other)
        )
    def __truediv__(self, other):
        return (
            mint(
                self.x * pow(other.x, MOD - 2, MOD)
            ) if isinstance(other, mint) else
            mint(self.x * pow(other, MOD - 2, MOD))
        )
    def __pow__(self, other):
        return (
            mint(pow(self.x, other.x, MOD)) if isinstance(other, mint) else
            mint(pow(self.x, other, MOD))
        )
    __radd__ = __add__
    def __rsub__(self, other):
        return (
            mint(other.x - self.x) if isinstance(other, mint) else
            mint(other - self.x)
        )
    __rmul__ = __mul__
    def __rmod__(self, other):
        return (
            mint(other.x % self.x) if isinstance(other, mint) else
            mint(other % self.x)
        )
    def __rtruediv__(self, other):
        return (
            mint(
                other.x * pow(self.x, MOD - 2, MOD)
            ) if isinstance(other, mint) else
            mint(other * pow(self.x, MOD - 2, MOD))
        )
    def __rpow__(self, other):
        return (
            mint(pow(other.x, self.x, MOD)) if isinstance(other, mint) else
            mint(pow(other, self.x, MOD))
        )

class comb():
    # class <mint> should be imported
    def __init__(self, n):
        self.n = n
        fact = [0]*(n+1) # 1-indexed
        ifact = [0]*(n+1) # 逆元
        fact[0] = mint(1)
        for i in range(1, n+1):
            fact[i] = fact[i-1]*i
        ifact[-1] = pow(fact[-1], MOD-2)
        for i in range(n, 0, -1):
            ifact[i-1] = ifact[i]*i
        self.fact = fact
        self.ifact = ifact
    def calc(self, n, k):
        if n == 0:
            return 1
        if k<0 or k>n:
            return 0
        return self.fact[n]*self.ifact[k]*self.ifact[n-k]
cb = comb(200005)

class datum:
    def __init__(self, size=0, case=None):
        self.size = size
        if case is None:
            self.case = mint(1)
        else:    
            self.case = case

def merge(d, plus):
    now = copy(d)
    now.size += plus.size
    now.case *= plus.case
    now.case *= cb.ifact[plus.size]
    return now

def add_root(d):
    now = copy(d)
    now.case *= cb.fact[now.size]
    now.size += 1
    return now

def dfs(u,p=-1):
    now = datum()
    for v in to[u]:
        if v == p:
            continue
        dp[u][v] = dfs(v,u)
        now = merge(now,dp[u][v])
    now = add_root(now)
    return now

ans = [mint(0) for _ in range(n)]
def bfs(u,p=-1,pdp=None):
    for v in to[u]:
        if v == p:
            dp[u][v] = pdp
    deg = len(to[u])
    l = [datum() for _ in range(deg+1)]
    r = [datum() for _ in range(deg+1)]
    for i in range(deg):
        l[i+1] = merge(l[i], dp[u][to[u][i]])
    for i in reversed(range(1,deg+1)):
        r[i-1] = merge(r[i], dp[u][to[u][i-1]])

    ans[u] = add_root(l[-1]).case

    for i in range(deg):
        v = to[u][i]
        if v == p:
            continue
        argdp = datum()
        argdp.size += l[i].size + r[i+1].size
        argdp.case *= l[i].case * r[i+1].case
        bfs(v,u,add_root(argdp))







to = [list() for _ in range(n)]
dp = [dict() for _ in range(n)]
for i in range(n-1):
    a,b = map(int, input().split())
    a -=  1
    b -= 1
    to[a].append(b)
    to[b].append(a)

dfs(0)
bfs(0)

print(*ans)

Submission status: Runtime Error

Solution code:
from copy import deepcopy as copy
n = int(input())
MOD = 10**9+7
class mint:
    def __init__(self, x):
        self.x = x % MOD if isinstance(x, int) else int(x) % MOD
    def __str__(self):
        return str(self.x)
    __repr__ = __str__
    def __iadd__(self, other):
        self.x += other.x if isinstance(other, mint) else other
        self.x -= MOD if self.x >= MOD else 0
        return self
    def __isub__(self, other):
        self.x += MOD-other.x if isinstance(other, mint) else MOD-other
        self.x -= MOD if self.x >= MOD else 0
        return self
    def __imul__(self, other):
        self.x *= other.x if isinstance(other, mint) else other
        self.x %= MOD
        return self
    def __imod__(self, other):
        self.x %= other.x if isinstance(other, mint) else other
        self.x %= MOD
        return self
    def __add__(self, other):
        return (
            mint(self.x + other.x) if isinstance(other, mint) else
            mint(self.x + other)
        )
    def __sub__(self, other):
        return (
            mint(self.x - other.x) if isinstance(other, mint) else
            mint(self.x - other)
        )
    def __mul__(self, other):
        return (
            mint(self.x * other.x) if isinstance(other, mint) else
            mint(self.x * other)
        )
    def __mod__(self, other):
        return (
            mint(self.x % other.x) if isinstance(other, mint) else
            mint(self.x % other)
        )
    def __truediv__(self, other):
        return (
            mint(
                self.x * pow(other.x, MOD - 2, MOD)
            ) if isinstance(other, mint) else
            mint(self.x * pow(other, MOD - 2, MOD))
        )
    def __pow__(self, other):
        return (
            mint(pow(self.x, other.x, MOD)) if isinstance(other, mint) else
            mint(pow(self.x, other, MOD))
        )
    __radd__ = __add__
    def __rsub__(self, other):
        return (
            mint(other.x - self.x) if isinstance(other, mint) else
            mint(other - self.x)
        )
    __rmul__ = __mul__
    def __rmod__(self, other):
        return (
            mint(other.x % self.x) if isinstance(other, mint) else
            mint(other % self.x)
        )
    def __rtruediv__(self, other):
        return (
            mint(
                other.x * pow(self.x, MOD - 2, MOD)
            ) if isinstance(other, mint) else
            mint(other * pow(self.x, MOD - 2, MOD))
        )
    def __rpow__(self, other):
        return (
            mint(pow(other.x, self.x, MOD)) if isinstance(other, mint) else
            mint(pow(other, self.x, MOD))
        )

class comb():
    # class <mint> should be imported
    def __init__(self, n):
        self.n = n
        fact = [0]*(n+1) # 1-indexed
        ifact = [0]*(n+1) # 逆元
        fact[0] = mint(1)
        for i in range(1, n+1):
            fact[i] = fact[i-1]*i
        ifact[-1] = pow(fact[-1], MOD-2)
        for i in range(n, 0, -1):
            ifact[i-1] = ifact[i]*i
        self.fact = fact
        self.ifact = ifact
    def calc(self, n, k):
        if n == 0:
            return 1
        if k<0 or k>n:
            return 0
        return self.fact[n]*self.ifact[k]*self.ifact[n-k]
cb = comb(200005)

class datum:
    def __init__(self, size=0, case=mint(1)):
        self.size = size
        self.case = case

def merge(d, p):
    now = copy(d)
    plus = copy(p)
    now.size += plus.size
    now.case *= plus.case
    now.case *= cb.ifact[plus.size]
    return now

def merge2(a,b):
    a2 = copy(a)
    b2 = copy(b)
    ressize = a2.size + b2.size
    rescase = a2.case* b2.case
    return datum(ressize, rescase)
def add_root(d):
    now = copy(d)
    now.case *= cb.fact[now.size]
    now.size += 1
    return now

def dfs(u,p=-1):
    now = datum()
    for v in to[u]:
        if v == p:
            continue
        dp[u][v] = dfs(v,u)
        now = merge(now,dp[u][v])
    now = add_root(now)
    return now

ans = [mint(0) for _ in range(n)]
def bfs(u,p=-1,pdp=datum()):
    for v in to[u]:
        if v == p:
            dp[u][v] = pdp
    deg = len(to[u])
    l = [datum() for _ in range(deg+1)]
    r = [datum() for _ in range(deg+1)]
    for i in range(deg):
        l[i+1] = merge(l[i], dp[u][to[u][i]])
    for i in reversed(range(1,deg+1)):
        r[i-1] = merge(r[i], dp[u][to[u][i-1]])

    ans[u] = add_root(l[-1]).case

    for i in range(deg):
        v = to[u][i]
        if v == p:
            continue
        lm = copy(l[i])
        rm = copy(r[i+1])
        bfs(v,u,add_root(merge2(lm,rm)))







to = [list() for _ in range(n)]
dp = [dict() for _ in range(n)]
for i in range(n-1):
    a,b = map(int, input().split())
    a -=  1
    b -= 1
    to[a].append(b)
    to[b].append(a)

dfs(0)
bfs(0)

print(*ans)

Submission status: Runtime Error

Solution code:

from collections import defaultdict
n = int(input())
ns = defaultdict(set)
for _ in range(n-1):
    u,v = map(int, input().split())
    ns[u-1].add(v-1)
    ns[v-1].add(u-1)

    
M = 10**9+7 # 出力の制限
N = n # 必要なテーブルサイズ

g1 = [None] * (N+1) # 元テーブル
g2 = [None] * (N+1) #逆元テーブル
inverse = [None] * (N+1) #逆元テーブル計算用テーブル
g1[0] = g1[1] = g2[0] = g2[1] = 1
inverse[0], inverse[1] = [0, 1] 

for i in range( 2, N + 1 ):
    g1[i] = ( g1[i-1] * i ) % M 
    inverse[i] = ( -inverse[M % i] * (M//i) ) % M # ai+b==0 mod M <=> i==-b*a^(-1) <=> i^(-1)==-b^(-1)*aより
    g2[i] = (g2[i-1] * inverse[i]) % M 

    

ans = {}
def sub(i, j):
    if (i,j) in ans:
        return ans[i,j]
    if len(ns[j])==1 and i in ns[j]:
        ans[i,j] = (1, 1)
        return (1, 1)
    
    count = 1
    sum_size = 0
    for k in ns[j]:
        if k==i:
            continue
        val, size = sub(j, k)
        count = (count * val) % M
        count = (count * g2[size]) % M
        sum_size += size
    count = (count * g1[sum_size]) % M
    ans[i,j] = (count, sum_size+1)
    return (count, sum_size+1)

for u in range(n):
    count = 1
    sum_size = 0
    for k in ns[u]:
        val, size = sub(u, k)
        count = (count * val) % M
        count = (count * g2[size]) % M
        sum_size += size
    count = (count * g1[sum_size]) % M
    print(count)

Submission status: Runtime Error

Solution code:
def main():
    n = int(input())
    ab = [list(map(int, input().split())) for _ in [0]*(n-1)]
    mod = 10**9+7

    g = [[] for _ in [0]*n]
    [g[a-1].append(b-1) for a, b in ab]
    [g[b-1].append(a-1) for a, b in ab]

    mod = 10**9+7
    fact = [1, 1]
    for i in range(2, 10**5):
        fact.append(fact[-1]*i % mod)

    def inv_n(n):
        return pow(n, mod-2, mod)

    def nCr(n, r, mod=10**9+7):
        return pow(fact[n-r]*fact[r] % mod, mod-2, mod)*fact[n] % mod

    class rerooting():
        # addは頂点iに頂点jを根とする部分木（DPの値：x）をくっつけるときの補正
        def __init__(self, tree, ini):
            # merge:頂点aにbをマージするときのモノイド
            # adj_bu:ボトムアップ時の調整（a:値,i:頂点）
            # adj_td:トップダウン時の調整（a:値,i:頂点,p:親）
            # adj_fin:最終調整（a:値,i:頂点）
            def merge(a, b): return a * b % mod
            def adj_bu(a, i): return a * inv_n(size[i]) % mod
            def adj_td(a, i, p): return a * inv_n(n-size[i]) % mod
            def adj_fin(a, i): return a * fact[n-1] % mod

            # トポロジカルソートをする
            # T:木の隣接グラフ表現をset化
            # P:親
            # q:キュー
            # order:トポソしたもの
            T = [set(i) for i in tree]
            P = [-1]*n
            q = [0]
            order = []
            while q:
                i = q.pop()
                order.append(i)
                for a in T[i]:
                    if a != P[i]:
                        P[a] = i
                        T[a].remove(i)
                        q.append(a)

            # Tをリストに変換
            T = [list(i) for i in T]

            # サイズの処理を先に行う
            # size[i]:0を根とする根付き木における、iを根とする部分木の大きさ
            size = [1]*n
            for i in order[1:][::-1]:
                size[P[i]] += size[i]

            # ボトムアップ処理をする
            # ME:マージした値を一時保存
            # DP:DP値、MEを調整したもの
            ME = [ini]*n
            DP = [0]*n
            for i in order[1:][::-1]:
                DP[i] = adj_bu(ME[i], i)
                p = P[i]
                ME[p] = merge(ME[p], DP[i])
            DP[order[0]] = adj_fin(ME[order[0]], order[0])
            TD = [ini]*n

            # トップダウン処理をする
            for i in order:
                # 左からDP（結果はTDに入れている）
                ac = TD[i]
                for j in T[i]:
                    TD[j] = ac
                    ac = merge(ac, DP[j])
                # 右からDP（結果はacに入れている、一度しか使わないのでacで問題ない）
                ac = ini
                for j in T[i][::-1]:
                    TD[j] = adj_td(merge(TD[j], ac), j, i)
                    ac = merge(ac, DP[j])
                    DP[j] = adj_fin(merge(ME[j], TD[j]), j)
            for i in DP:
                print(i)

    rerooting(g, 1)


main()

Submission status: Runtime Error

Solution code:
def main():
    n = int(input())
    ab = [list(map(int, input().split())) for _ in [0]*(n-1)]
    mod = 10**9+7

    g = [[] for _ in [0]*n]
    [g[a-1].append(b-1) for a, b in ab]
    [g[b-1].append(a-1) for a, b in ab]

    mod = 10**9+7
    fact = [1, 1]
    for i in range(2, 10**5):
        fact.append(fact[-1]*i % mod)

    def inv_n(n):
        return pow(n, mod-2, mod)

    def nCr(n, r, mod=10**9+7):
        return pow(fact[n-r]*fact[r] % mod, mod-2, mod)*fact[n] % mod

    class rerooting():
        # addは頂点iに頂点jを根とする部分木（DPの値：x）をくっつけるときの補正
        def __init__(self, tree, ini):
            # merge:頂点aにbをマージするときのモノイド
            # adj_bu:ボトムアップ時の調整（a:値,i:頂点）
            # adj_td:トップダウン時の調整（a:値,i:頂点,p:親）
            # adj_fin:最終調整（a:値,i:頂点）
            def merge(a, b): return a * b % mod
            def adj_bu(a, i): return a * inv_n(size[i]) % mod
            def adj_td(a, i, p): return a * inv_n(n-size[i]) % mod
            def adj_fin(a, i): return a * fact[n-1] % mod

            # トポロジカルソートをする
            # T:木の隣接グラフ表現をset化
            # P:親
            # q:キュー
            # order:トポソしたもの
            T = [set(i) for i in tree]
            P = [-1]*n
            q = [0]
            order = []
            while q:
                i = q.pop()
                order.append(i)
                for a in T[i]:
                    if a != P[i]:
                        P[a] = i
                        T[a].remove(i)
                        q.append(a)

            # Tをリストに変換
            T = [list(i) for i in T]

            # サイズの処理を先に行う
            # size[i]:0を根とする根付き木における、iを根とする部分木の大きさ
            size = [1]*n
            for i in order[1:][::-1]:
                size[P[i]] += size[i]

            # ボトムアップ処理をする
            # ME:マージした値を一時保存
            # DP:DP値、MEを調整したもの
            ME = [ini]*n
            DP = [0]*n
            for i in order[1:][::-1]:
                DP[i] = adj_bu(ME[i], i)
                p = P[i]
                ME[p] = merge(ME[p], DP[i])
            DP[order[0]] = adj_fin(ME[order[0]], order[0])
            TD = [ini]*n
            
            # トップダウン処理をする
            for i in order:
                # 左からDP（結果はTDに入れている）
                ac = TD[i]
                for j in T[i]:
                    TD[j] = ac
                    ac = merge(ac, DP[j])
                # 右からDP（結果はacに入れている、一度しか使わないのでacで問題ない）
                ac = ini
                for j in T[i][::-1]:
                    TD[j] = adj_td(merge(TD[j], ac), j, i)
                    ac = merge(ac, DP[j])
                    DP[j] = adj_fin(merge(ME[j], TD[j]), j)
            print(DP)

    rerooting(g, 1)


main()

Submission status: Runtime Error

Solution code:
def main():
    n = int(input())
    ab = [list(map(int, input().split())) for _ in [0]*(n-1)]
    g = [[] for _ in [0]*n]
    [g[a-1].append(b-1) for a, b in ab]
    [g[b-1].append(a-1) for a, b in ab]
    mod = 10**9+7
    fact = [1, 1]
    for i in range(2, 200001):
        fact.append(fact[-1]*i % mod)

    def nCr(n, r, mod=10**9+7):
        return pow(fact[n-r]*fact[r], mod-2, mod)*fact[n] % mod

    class rerooting():
        # addは頂点iに頂点jを根とする部分木（DPの値：x）をくっつけるときの補正
        def __init__(self, tree, ini):
            # 頂点iについて、jが根のときのDPの値を求める（アクセス時間を考慮してここで定義）
            def add(i, j, x):
                return x+1

            def monoid(i, j):
                return i+j

            def monoid2(i, j):
                return i*j % mod

            def calc(i, j):
                root = tree_d[i][j]+1
                try:
                    return monoid(tc_l[i][root-1], tc_r[i][root])
                except:
                    return tc_l[i][root-1]

            def calc2(i, j):
                root = tree_d[i][j]+1
                try:
                    return monoid2(tc_l2[i][root-1], tc_r2[i][root]) *\
                        nCr(tc_l[i][root-1]+tc_r[i][root], tc_l[i][root-1])
                except:
                    return tc_l2[i][root-1]

            size = len(tree)
            dp, dp2, order, q, anc = [ini]*size, [1]*size, [], [0], [-1]*n
            oa, qa, qp = order.append, q.append, q.pop
            tree_d = [{k: j for j, k in enumerate(i)} for i in g]
            g_size = [len(i) for i in g]
            tc_l = [[ini]*(i+1) for i in g_size]
            tc_r = [[ini]*i for i in g_size]
            tc_l2 = [[1]*(i+1) for i in g_size]
            tc_r2 = [[1]*i for i in g_size]

            # トポロジカル順序をorderに記録、0を根とする根付き木上のiの祖先をanc[i]とする
            while q:
                i = qp()
                a = anc[i]
                oa(i)
                for j in g[i]:
                    if j != a:
                        qa(j)
                        anc[j] = i

            # dpおよびtree_preに記録
            for i in order[:0:-1]:
                a = anc[i]
                t = tree_d[a][i]
                d = dp2[i]
                tc_l2[a][t+1], tc_r2[a][t] = d, d
                d = add(a, i, dp[i])
                tc_l[a][t+1], tc_r[a][t], dp[a] = d, d, monoid(dp[a], d)
                dp2[a] = dp2[a]*dp2[i]*nCr(dp[a], dp[i]+1) % mod

            # 頂点0のみ先に処理
            for j in range(1, g_size[0]+1):
                tc_l[0][j] = monoid(tc_l[0][j], tc_l[0][j-1])
                tc_l2[0][j] = tc_l2[0][j]*tc_l2[0][j-1] * \
                    nCr(tc_l[0][j], tc_l[0][j-1]) % mod
            for j in range(g_size[0]-1, 0, -1):
                tc_r[0][j] = monoid(tc_r[0][j], tc_r[0][j+1])
                tc_r2[0][j] = tc_r2[0][j]*tc_r2[0][j+1] * \
                    nCr(tc_r[0][j], tc_r[0][j+1]) % mod

            # 行きがけ順に処理
            for i in order[1:]:
                a = anc[i]
                d, c, c2, length = tree_d[i][a], add(
                    a, i, calc(a, i)), calc2(a, i), g_size[i]

                tc_l[i][d+1], tc_r[i][d] = c, c
                tc_l2[i][d+1], tc_r2[i][d] = c2, c2

                for j in range(1, length+1):
                    tc_l[i][j] = monoid(tc_l[i][j], tc_l[i][j-1])
                    tc_l2[i][j] = tc_l2[i][j]*tc_l2[i][j-1] * \
                        nCr(tc_l[i][j], tc_l[i][j-1]) % mod
                for j in range(length-2, 0, -1):
                    tc_r[i][j] = monoid(tc_r[i][j+1], tc_r[i][j])
                    tc_r2[i][j] = tc_r2[i][j]*tc_r2[i][j+1] * \
                        nCr(tc_r[i][j], tc_r[i][j+1]) % mod
                dp[i] = tc_l[i][-1]
                dp2[i] = tc_l2[i][-1]

            # アトリビュートに格納
            for i in dp2:
                print(i)

    rerooting(g, 0)


main()

Submission status: Runtime Error

Solution code:
from sys import setrecursionlimit
from math import factorial

setrecursionlimit(2 * 10 ** 5)

def comb(n, r):
  return factorial(n) / factorial(r) / factorial(n - r)

class Node:
  def __init__(self, node_id):
    self.id = node_id
    self.children = []
    self.size = 1

  def add_child(self, node):
    self.children.append(node)

  @staticmethod
  def prepare_nodes(n):
    nodes = tuple([Node(i) for i in range(n)])
    for _ in range(n - 1):
      a, b = sorted(map(lambda x: int(x) - 1, input().split()))
      nodes[a].add_child(nodes[b])

    return nodes


def main():
  n = int(input())
  nodes = Node.prepare_nodes(n)

  dp = [0] * n

  def f(node):
    dpv = 1
    denominator = 1
    for child in node.children:
      f(child)
      dpv *= dp[child.id]
      denominator *= factorial(child.size)
      node.size += child.size

    dpv *= factorial(node.size - 1) // denominator

    dp[node.id] = dpv

  f(nodes[0])

  def g(node, parent):
    if parent:
      parent_dp = dp[parent.id]
      parent_dp = parent_dp // (dp[node.id] * int(comb(n - 1, node.size)))

      dp[node.id] *= parent_dp * int(comb(n - 1, n - node.size))

    for child in node.children:
      g(child, node)

  g(nodes[0], None)

  for ans in dp:
    print(ans)


main()

Submission status: Runtime Error

Solution code:
from math import factorial


def comb(n, r):
  return factorial(n) / factorial(r) / factorial(n - r)

class Node:
  def __init__(self, node_id):
    self.id = node_id
    self.children = []
    self.size = 1

  def add_child(self, node):
    self.children.append(node)

  @staticmethod
  def prepare_nodes(n):
    nodes = tuple([Node(i) for i in range(n)])
    for _ in range(n - 1):
      a, b = sorted(map(lambda x: int(x) - 1, input().split()))
      nodes[a].add_child(nodes[b])

    return nodes


def main():
  n = int(input())
  nodes = Node.prepare_nodes(n)

  dp = [0] * n

  def f(node):
    dpv = 1
    denominator = 1
    for child in node.children:
      f(child)
      dpv *= dp[child.id]
      denominator *= factorial(child.size)
      node.size += child.size

    dpv *= factorial(node.size - 1) // denominator

    dp[node.id] = dpv

  f(nodes[0])

  def g(node, parent):
    if parent:
      parent_dp = dp[parent.id]
      parent_dp = parent_dp // (dp[node.id] * int(comb(n - 1, node.size)))

      dp[node.id] *= parent_dp * int(comb(n - 1, n - node.size))

    for child in node.children:
      g(child, node)

  g(nodes[0], None)

  for ans in dp:
    print(ans)


main()