Problem:
 Score : 100 points    Problem Statement There is a tree with N vertices, numbered 1, 2, \ldots, N .
For each i ( 1 \leq i \leq N - 1 ), the i -th edge connects Vertex x_i and y_i .  Taro has decided to paint each vertex in white or black, so that any black vertex can be reached from any other black vertex by passing through only black vertices.  You are given a positive integer M .
For each v ( 1 \leq v \leq N ), answer the following question:   Assuming that Vertex v has to be black, find the number of ways in which the vertices can be painted, modulo M .       Constraints  All values in input are integers.  1 \leq N \leq 10^5  2 \leq M \leq 10^9  1 \leq x_i, y_i \leq N  The given graph is a tree.         Input Input is given from Standard Input in the following format:  N  M  x_1  y_1  x_2  y_2  :  x_{N - 1}  y_{N - 1}       Output Print N lines.
The v -th ( 1 \leq v \leq N ) line should contain the answer to the following question:   Assuming that Vertex v has to be black, find the number of ways in which the vertices can be painted, modulo M .         Sample Input 1 3 100
1 2
2 3      Sample Output 1 3
4
3  There are seven ways to paint the vertices, as shown in the figure below.
Among them, there are three ways such that Vertex 1 is black, four ways such that Vertex 2 is black and three ways such that Vertex 3 is black.        Sample Input 2 4 100
1 2
1 3
1 4      Sample Output 2 8
5
5
5       Sample Input 3 1 100      Sample Output 3 1       Sample Input 4 10 2
8 5
10 8
6 5
1 5
4 8
2 10
3 6
9 2
1 7      Sample Output 4 0
0
1
1
1
0
1
0
1
1  Be sure to print the answers modulo M .

Solution (Python):
import sys
from collections import deque
stdin = sys.stdin


def ni(): return int(ns())


def na(): return list(map(int, stdin.readline().split()))


def naa(N): return [na() for _ in range(N)]


def ns(): return stdin.readline().rstrip()  


def make_tree_0index(N):
    edge_dic = {}
    for _ in range(N-1):
        x, y = na()
        x -= 1
        y -= 1
        if x in edge_dic:
            edge_dic[x].append(y)
        else:
            edge_dic[x] = [y]
        if y in edge_dic:
            edge_dic[y].append(x)
        else:
            edge_dic[y] = [x]
    return edge_dic


N, M = na()
if N == 1:
    print(1)
    exit()
edge_dic = make_tree_0index(N)


parent_array = [-2] * N
parent_array[0] = -1
node1 = deque([0])
node2 = deque([0])
node3 = deque([0])

while(len(node1)):
    n = node1.popleft()
    for v in edge_dic[n]:
        if parent_array[v] == -2:
            parent_array[v] = n
            node1.append(v)
            node2.append(v)
            node3.append(v)

ans1 = [0] * N

while(len(node2)):
    n = node2.pop()
    ans1[n] = 1
    for v in edge_dic[n]:
        if parent_array[n] == v:
            continue
        ans1[n] = (ans1[n] * (ans1[v]+1)) % M

ans2 = [0] * N

subans2 = [0] * N

while(len(node3)):
    n = node3.popleft()
    ans2[n] = 1
    if n != 0:
        ans2[n] = (ans2[n] * ans2[parent_array[n]] * subans2[n] + 1) % M

    reverse = [1]
    right = 1
    for v in edge_dic[n][::-1]:
        if parent_array[n] == v:
            continue
        right = (right * (ans1[v] + 1)) % M
        reverse.append(right)
    reverse.pop()

    left = 1
    for v in edge_dic[n]:
        if parent_array[n] == v:
            continue
        right = reverse.pop()
        subans2[v] = (left * right) % M
        left = (left * (ans1[v]+1)) % M


ans = [a*b % M for a, b in zip(ans1, ans2)]
print("\n".join(map(str, ans)))

Solution (Python):
class Graph:

    def __init__(self, n_vertices, edges, directed=True):
        self.n_vertices = n_vertices
        self.edges = edges
        self.directed = directed

    @property
    def adj(self):
        try:
            return self._adj
        except AttributeError:
            adj = [[] for _ in range(self.n_vertices)]
            if self.directed:
                for u,v in self.edges:
                    adj[u].append(v)
            else:
                for u,v in self.edges:
                    adj[u].append(v)
                    adj[v].append(u)
            self._adj = adj
            return adj

class RootedTree(Graph):
    def __init__(self, n_vertices, edges, root_vertex):
        self.root = root_vertex
        super().__init__(n_vertices, edges, False)

    @property
    def parent(self):
        try:
            return self._parent
        except AttributeError:
            adj = self.adj
            parent = [None]*self.n_vertices
            parent[self.root] = -1
            stack = [self.root]
            for _ in range(self.n_vertices):
                v = stack.pop()
                for u in adj[v]:
                    if parent[u] is None:
                        parent[u] = v
                        stack.append(u)
            self._parent = parent
            return parent

    @property
    def children(self):
        try:
            return self._children
        except AttributeError:
            children = [None]*self.n_vertices
            for v,(l,p) in enumerate(zip(self.adj,self.parent)):
                children[v] = [u for u in l if u != p]
            self._children = children
            return children

    @property
    def dfs_order(self):
        try:
            return self._dfs_order
        except AttributeError:
            order = [None]*self.n_vertices
            children = self.children
            stack = [self.root]
            for i in range(self.n_vertices):
                v = stack.pop()
                order[i] = v
                for u in children[v]:
                    stack.append(u)
            self._dfs_order = order
            return order


from functools import reduce
from itertools import accumulate,chain
def rerooting(rooted_tree, merge, identity, finalize):
    """
    merge: (T,T) -> T, (T, merge)はモノイド
    identity: 単位元
    finalize: T -> T
 
    以下の形で書けるdpは対応可能
    dp[u,v] = finalize(merge(dp[v,k] for k in adj[v] if k != u), v)
    ただし(u,v)は辺
    """
    N = rooted_tree.n_vertices
    parent = rooted_tree.parent
    children = rooted_tree.children
    order = rooted_tree.dfs_order

    
    dp_down = [None]*N
    for v in reversed(order[1:]):
        dp_down[v] = finalize(reduce(merge,
            (dp_down[c] for c in children[v]),
            identity), v)

    
    dp_up = [None]*N
    dp_up[0] = identity
    for v in order:
        if len(children[v]) == 0:
            continue
        temp = (dp_up[v],)+tuple(dp_down[u] for u in children[v])+(identity,)
        left = accumulate(temp[:-2],merge)
        right = tuple(accumulate(reversed(temp[2:]),merge))
        for u,l,r in zip(children[v],left,reversed(right)):
            dp_up[u] = finalize(merge(l,r), v)

    res = [None]*N
    for v,l in enumerate(children):
        res[v] = reduce(merge,
                    (dp_down[u] for u in children[v]),
                    identity)
        res[v] = finalize(merge(res[v], dp_up[v]), v)
    return res

def solve(N,M,E):

    tree = RootedTree(N,E,0)

    def merge(x,y):
        return (x*y)%M
    def finalize(x,v):
        return x+1

    res = rerooting(tree,merge,1,finalize)
    return [v-1 for v in res]

import sys
read = sys.stdin.buffer.read
readline = sys.stdin.buffer.readline

if __name__ == '__main__':
    N,M = map(int,readline().split())

    temp = map(lambda x: int(x)-1,read().split())
    E = zip(temp,temp)
    print(*solve(N,M,E),sep='\n')

Solution (Python):
class Graph:

    def __init__(self, n_vertices, edges, directed=True):
        self.n_vertices = n_vertices
        self.edges = edges
        self.directed = directed

    @property
    def adj(self):
        try:
            return self._adj
        except AttributeError:
            adj = [[] for _ in range(self.n_vertices)]
            if self.directed:
                for u,v in self.edges:
                    adj[u].append(v)
            else:
                for u,v in self.edges:
                    adj[u].append(v)
                    adj[v].append(u)
            self._adj = adj
            return adj

class RootedTree(Graph):
    def __init__(self, n_vertices, edges, root_vertex):
        self.root = root_vertex
        super().__init__(n_vertices, edges, False)

    @property
    def parent(self):
        try:
            return self._parent
        except AttributeError:
            adj = self.adj
            parent = [None]*self.n_vertices
            parent[self.root] = -1
            stack = [self.root]
            for _ in range(self.n_vertices):
                v = stack.pop()
                for u in adj[v]:
                    if parent[u] is None:
                        parent[u] = v
                        stack.append(u)
            self._parent = parent
            return parent

    @property
    def children(self):
        try:
            return self._children
        except AttributeError:
            children = [None]*self.n_vertices
            for v,(l,p) in enumerate(zip(self.adj,self.parent)):
                children[v] = [u for u in l if u != p]
            self._children = children
            return children

    @property
    def dfs_order(self):
        try:
            return self._dfs_order
        except AttributeError:
            order = [None]*self.n_vertices
            children = self.children
            stack = [self.root]
            for i in range(self.n_vertices):
                v = stack.pop()
                order[i] = v
                for u in children[v]:
                    stack.append(u)
            self._dfs_order = order
            return order


from functools import reduce
from itertools import accumulate,chain
def rerooting(rooted_tree, merge, identity, finalize):
    """
    merge: (T,T) -> T, (T, merge)はモノイド
    identity: 単位元
    finalize: T -> T
 
    以下の形で書けるdpは対応可能
    dp[u,v] = finalize(merge(dp[v,k] for k in adj[v] if k != u), v)
    ただし(u,v)は辺
    """
    N = rooted_tree.n_vertices
    parent = rooted_tree.parent
    children = rooted_tree.children
    order = rooted_tree.dfs_order

    
    dp_down = [None]*N
    for v in reversed(order[1:]):
        dp_down[v] = finalize(reduce(merge,
            (dp_down[c] for c in children[v]),
            identity), v)

    
    dp_up = [None]*N
    dp_up[0] = identity
    for v in order:
        if len(children[v]) == 0:
            continue
        temp = (dp_up[v],)+tuple(dp_down[u] for u in children[v])+(identity,)
        left = accumulate(temp[:-2],merge)
        right = tuple(accumulate(reversed(temp[2:]),merge))
        for u,l,r in zip(children[v],left,reversed(right)):
            dp_up[u] = finalize(merge(l,r), v)

    res = [None]*N
    for v,l in enumerate(children):
        res[v] = reduce(merge,
                    (dp_down[u] for u in children[v]),
                    identity)
        res[v] = finalize(merge(res[v], dp_up[v]), v)
    return res

def solve(N,M,E):

    tree = RootedTree(N,E,0)

    def merge(x,y):
        return (x*y)%M
    def finalize(x,v):
        return x+1

    res = rerooting(tree,merge,1,finalize)
    return [v-1 for v in res]


if __name__ == '__main__':
    N,M = map(int,input().split())
    E = [tuple(map(lambda x: int(x)-1, input().split())) for _ in range(N-1)]
    print(*solve(N,M,E),sep='\n')

Solution (Python):
class Graph:
    def __init__(self, n_vertices, edges, directed=True, weighted=False):
        self.n_vertices = n_vertices
        self.edges = edges
        self.directed = directed
        self.weighted = weighted

    @property
    def adj(self):
        try:
            return self._adj
        except AttributeError:
            adj = [[] for _ in range(self.n_vertices)]
            def d_w(e):
                adj[e[0]].append((e[1],e[2]))
            def ud_w(e):
                adj[e[0]].append((e[1],e[2]))
                adj[e[1]].append((e[0],e[2]))
            def d_uw(e):
                adj[e[0]].append(e[1])
            def ud_uw(e):
                adj[e[0]].append(e[1])
                adj[e[1]].append(e[0])
            helper = (ud_uw, d_uw, ud_w, d_w)[self.directed+self.weighted*2]
            for e in self.edges:
                helper(e)
            self._adj = adj
            return adj

class RootedTree(Graph):
    def __init__(self, n_vertices, edges, root_vertex):
        self.root = root_vertex
        super().__init__(n_vertices, edges, False, False)

    @property
    def parent(self):
        try:
            return self._parent
        except AttributeError:
            adj = self.adj
            parent = [None]*self.n_vertices
            parent[self.root] = -1
            stack = [self.root]
            for i in range(self.n_vertices):
                v = stack.pop()
                for u in adj[v]:
                    if parent[u] is None:
                        parent[u] = v
                        stack.append(u)
            self._parent = parent
            return parent

    @property
    def children(self):
        try:
            return self._children
        except AttributeError:
            children = [None]*self.n_vertices
            for v,(l,p) in enumerate(zip(self.adj,self.parent)):
                children[v] = [u for u in l if u != p]
            self._children = children
            return children

    @property
    def dfs_order(self):
        try:
            return self._dfs_order
        except AttributeError:
            order = [None]*self.n_vertices
            children = self.children
            stack = [self.root]
            for i in range(self.n_vertices):
                v = stack.pop()
                order[i] = v
                for u in children[v]:
                    stack.append(u)
            self._dfs_order = order
            return order

from functools import reduce
from itertools import accumulate,chain
def rerooting(rooted_tree, merge, identity, finalize):
    """
    merge: (T,T) -> T, (T, merge)はモノイド
    identity: 単位元
    finalize: T -> T

    以下の形で書けるdpは対応可能
    dp[u,v] = finalize(merge(dp[v,k] for k in adj[v] if k != u))
    ただし(u,v)は辺
    """
    N = rooted_tree.n_vertices
    parent = rooted_tree.parent
    children = rooted_tree.children
    order = rooted_tree.dfs_order

    
    dp_down = [None]*N
    for v in reversed(order[1:]):
        dp_down[v] = finalize(reduce(merge,
            (dp_down[c] for c in children[v]),
            identity))

    
    dp_up = [None]*N
    dp_up[0] = identity
    for v in order:
        if len(children[v]) == 0:
            continue
        temp = (dp_up[v],)+tuple(dp_down[u] for u in children[v])+(identity,)
        left = tuple(accumulate(temp,merge))
        right = tuple(accumulate(reversed(temp[2:]),merge))
        for u,l,r in zip(children[v],left,reversed(right)):
            dp_up[u] = finalize(merge(l,r))

    res = [None]*N
    for v,l in enumerate(children):
        res[v] = reduce(merge,
                    (dp_down[u] for u in children[v]),
                    identity)
        res[v] = finalize(merge(res[v], dp_up[v]))

    return res

def solve(N,M,E):

    tree = RootedTree(N,E,0)

    def merge(x,y):
        return (x*y)%M
    def finalize(x):
        return x+1

    res = rerooting(tree,merge,1,finalize)
    return [v-1 for v in res]


if __name__ == '__main__':
    N,M = map(int,input().split())
    E = [tuple(map(lambda x: int(x)-1, input().split())) for _ in range(N-1)]
    print(*solve(N,M,E),sep='\n')

Solution (Python):
class Graph:
    def __init__(self, n_vertices, edges, directed=True, weighted=False):
        self.n_vertices = n_vertices
        self.edges = edges
        self.directed = directed
        self.weighted = weighted

    @property
    def adj(self):
        try:
            return self._adj
        except AttributeError:
            adj = [[] for _ in range(self.n_vertices)]
            def d_w(e):
                adj[e[0]].append((e[1],e[2]))
            def ud_w(e):
                adj[e[0]].append((e[1],e[2]))
                adj[e[1]].append((e[0],e[2]))
            def d_uw(e):
                adj[e[0]].append(e[1])
            def ud_uw(e):
                adj[e[0]].append(e[1])
                adj[e[1]].append(e[0])
            helper = (ud_uw, d_uw, ud_w, d_w)[self.directed+self.weighted*2]
            for e in self.edges:
                helper(e)
            self._adj = adj
            return adj

class RootedTree(Graph):
    def __init__(self, n_vertices, edges, root_vertex):
        self.root = root_vertex
        super().__init__(n_vertices, edges, False, False)

    @property
    def parent(self):
        try:
            return self._parent
        except AttributeError:
            adj = self.adj
            parent = [None]*self.n_vertices
            parent[self.root] = -1
            stack = [self.root]
            for i in range(self.n_vertices):
                v = stack.pop()
                for u in adj[v]:
                    if parent[u] is None:
                        parent[u] = v
                        stack.append(u)
            self._parent = parent
            return parent

    @property
    def children(self):
        try:
            return self._children
        except AttributeError:
            children = [None]*self.n_vertices
            for v,(l,p) in enumerate(zip(self.adj,self.parent)):
                children[v] = [u for u in l if u != p]
            self._children = children
            return children

    @property
    def dfs_order(self):
        try:
            return self._dfs_order
        except AttributeError:
            order = [None]*self.n_vertices
            children = self.children
            stack = [self.root]
            for i in range(self.n_vertices):
                v = stack.pop()
                order[i] = v
                for u in children[v]:
                    stack.append(u)
            self._dfs_order = order
            return order

from functools import reduce
from itertools import accumulate,chain
def rerooting(rooted_tree, merge, identity, finalize):
    """
    merge: (T,T) -> T, (T, merge)はモノイド
    identity: 単位元
    finalize: T -> T

    以下の形で書けるdpは対応可能
    dp[u,v] = finalize(merge(dp[v,k] for k in adj[v] if k != u))
    ただし(u,v)は辺
    """
    N = rooted_tree.n_vertices
    parent = rooted_tree.parent
    children = rooted_tree.children
    order = rooted_tree.dfs_order

    
    dp_down = [None]*N
    for v in reversed(order[1:]):
        dp_down[v] = finalize(reduce(merge,
            (dp_down[c] for c in children[v]),
            identity))

    
    dp_up = [None]*N
    dp_up[0] = identity
    for v in order:
        if len(children[v]) == 0:
            continue
        temp = (dp_up[v],)+tuple(dp_down[u] for u in children[v])+(identity,)
        left = tuple(accumulate(temp,merge))
        right = tuple(accumulate(reversed(temp),merge))
        for i,u in enumerate(children[v]):
            dp_up[u] = finalize(merge(left[i],right[-i-3]))

    res = [None]*N
    for v,l in enumerate(children):
        res[v] = reduce(merge,
                    (dp_down[u] for u in children[v]),
                    identity)
        res[v] = finalize(merge(res[v], dp_up[v]))

    return res

def solve(N,M,E):

    tree = RootedTree(N,E,0)

    def merge(x,y):
        return (x*y)%M
    def finalize(x):
        return x+1

    res = rerooting(tree,merge,1,finalize)
    return [v-1 for v in res]


if __name__ == '__main__':
    N,M = map(int,input().split())
    E = [tuple(map(lambda x: int(x)-1, input().split())) for _ in range(N-1)]
    print(*solve(N,M,E),sep='\n')

Solution (Python):

from functools import reduce
from itertools import accumulate,chain
def rerooting(N, adj, merge, identity, finalize):
    """
    merge: (T,T) -> T, (T, merge)はモノイド
    identity: 単位元
    finalize: T -> T

    以下の形で書けるdpは対応可能
    dp[u,v] = finalize(merge(dp[v,k] for k in adj[v] if k != u))
    ただし(u,v)は辺
    """

    order = [None]*N
    parent = [None]*N
    parent[0] = -1
    stack = [0]
    for i in range(N):
        v = stack.pop()
        order[i] = v
        for u in adj[v]:
            if parent[u] is None:
                parent[u] = v
                stack.append(u)

    
    dp_down = [None]*N
    for v in reversed(order[1:]):
        p = parent[v]
        dp_down[v] = finalize(reduce(merge,
            (dp_down[c] for c in adj[v] if c != p),
            identity))

    
    dp_up = [None]*N
    dp_up[0] = identity
    for v in order:
        p = parent[v]
        if len(adj[v]) == 1 and adj[v][0] == p:
            continue
        temp = (dp_up[v],)+tuple(dp_down[u] for u in adj[v] if u != p)+(identity,)
        left = tuple(accumulate(temp,merge))
        right = tuple(accumulate(reversed(temp),merge))
        i = 0
        for u in adj[v]:
            if u != p:
                dp_up[u] = finalize(merge(left[i],right[-i-3]))
                i += 1

    for v,l in enumerate(adj):
        order[v] = reduce(merge,
                    (dp_down[u] for u in adj[v] if u != parent[v]),
                    identity)
        order[v] = finalize(merge(order[v], dp_up[v]))

    return order

def solve(N,M,E):

    adj = [[] for _ in range(N)]
    for a,b in E:
        adj[a].append(b)
        adj[b].append(a)

    def merge(x,y):
        return (x*y)%M
    def finalize(x):
        return x+1

    res = rerooting(N,adj,merge,1,finalize)
    return [v-1 for v in res]


if __name__ == '__main__':
    N,M = map(int,input().split())
    E = [tuple(map(lambda x: int(x)-1, input().split())) for _ in range(N-1)]
    print(*solve(N,M,E),sep='\n')

Solution (Python):

from functools import reduce
from itertools import accumulate,chain
def rerooting(N, adj, merge, identity, finalize):
    """
    merge: (T,T) -> T, (T, merge)はモノイド
    identity: 単位元
    finalize: T -> T

    以下の形で書けるdpは対応可能
    dp[u,v] = finalize(merge(dp[v,k] for k in adj[v] if k != u))
    ただし(u,v)は辺
    """

    order = [None]*N
    parent = [None]*N
    parent[0] = -1
    stack = [0]
    for i in range(N):
        v = stack.pop()
        order[i] = v
        for u in adj[v]:
            if parent[u] is None:
                parent[u] = v
                stack.append(u)

    
    dp_down = [None]*N
    for v in reversed(order[1:]):
        p = parent[v]
        dp_down[v] = finalize(reduce(merge,
            (dp_down[c] for c in adj[v] if c != p),
            identity))

    
    dp_up = [None]*N
    dp_up[0] = identity
    for v in order:
        p = parent[v]
        if len(adj[v]) == 1 and adj[v][0] == p:
            continue
        left = tuple(accumulate(
            chain((dp_up[v],),(dp_down[u] for u in adj[v] if u != p)),
            merge))
        right = tuple(accumulate(
            chain((identity,),(dp_down[u] for u in reversed(adj[v]) if u != p)),
            merge))
        i = 0
        for u in adj[v]:
            if u != p:
                dp_up[u] = finalize(merge(left[i],right[-i-2]))
                i += 1

    for v,l in enumerate(adj):
        order[v] = reduce(merge,
                    (dp_down[u] for u in adj[v] if u != parent[v]),
                    identity)
        order[v] = finalize(merge(order[v], dp_up[v]))

    return order

def solve(N,M,E):

    adj = [[] for _ in range(N)]
    for a,b in E:
        adj[a].append(b)
        adj[b].append(a)

    def merge(x,y):
        return (x*y)%M
    def finalize(x):
        return x+1

    res = rerooting(N,adj,merge,1,finalize)
    return [v-1 for v in res]


if __name__ == '__main__':
    N,M = map(int,input().split())
    E = [tuple(map(lambda x: int(x)-1, input().split())) for _ in range(N-1)]
    print(*solve(N,M,E),sep='\n')

Solution (Python):

from functools import reduce
def rerooting(N, adj, merge, identity, finalize):
    """
    merge: (T,T) -> T, (T, merge)はモノイド
    identity: 単位元
    finalize: T -> T

    以下の形で書けるdpは対応可能
    dp[u,v] = finalize(merge(dp[v,k] for k in adj[v] if k != u))
    ただし(u,v)は辺
    """

    order = [None]*N
    parent = [None]*N
    parent[0] = -1
    stack = [0]
    for i in range(N):
        v = stack.pop()
        order[i] = v
        for u in adj[v]:
            if parent[u] is None:
                parent[u] = v
                stack.append(u)

    
    dp_down = [None]*N
    for v in reversed(order[1:]):
        p = parent[v]
        dp_down[v] = finalize(reduce(merge,
            (dp_down[c] for c in adj[v] if c != p),
            identity))

    
    dp_up = [None]*N
    dp_up[0] = identity
    for v in order:
        if len(adj[v]) == 1 and adj[v][0] == parent[v]:
            continue
        p = parent[v]
        left = [dp_up[v]]
        for u in adj[v]:
            if u != p:
                left.append(merge(left[-1],dp_down[u]))

        right = [identity]
        for u in reversed(adj[v]):
            if u != p:
                right.append(merge(dp_down[u],right[-1]))
        i = 0
        for u in adj[v]:
            if u != p:
                dp_up[u] = finalize(merge(left[i],right[-i-2]))
                i += 1

    for v,l in enumerate(adj):
        order[v] = reduce(merge,
                    (dp_down[u] for u in adj[v] if u != parent[v]),
                    identity)
        order[v] = finalize(merge(order[v], dp_up[v]))

    return order

def solve(N,M,E):

    adj = [[] for _ in range(N)]
    for a,b in E:
        adj[a].append(b)
        adj[b].append(a)

    def merge(x,y):
        return (x*y)%M
    def finalize(x):
        return x+1

    res = rerooting(N,adj,merge,1,finalize)
    return [v-1 for v in res]


if __name__ == '__main__':
    N,M = map(int,input().split())
    E = [tuple(map(lambda x: int(x)-1, input().split())) for _ in range(N-1)]
    print(*solve(N,M,E),sep='\n')

Solution (Python):
from collections import defaultdict
import sys
input=sys.stdin.readline


class Reroot:
    def __init__(self, N, e, merge, f, g):
        self.G = defaultdict(list)
        self.parents = [-1]*(N+1)
        self.dp = defaultdict(lambda: defaultdict(int))
        self.ans = [0]*(N+1)
        self.merge = merge
        self.f = f
        self.g = g
        self.e = e

    def add_edge(self, s, t):
        self.G[s].append(t)

    def build(self):
        self.dfs1(1)
        self.dfs2(1)
        return self.ans

    def dfs1(self, s):
        l = []
        q = [1]
        while q:
            s = q.pop()
            l.append(s)
            for t in self.G[s]:
                if t == self.parents[s]:
                    continue
                self.parents[t] = s
                q.append(t)

        for s in l[::-1]:
            v = self.e
            for t in self.G[s]:
                if t == self.parents[s]:
                    continue
                v = self.merge(v, self.f(self.dp[s][t], 1))
            self.dp[self.parents[s]][s] = self.g(v, 0)

    def dfs2(self, s):
        q = [(s, self.e)]
        while q:
            s, dp_p = q.pop()
            par = self.parents[s]
            for t in self.G[s]:
                if t == par:
                    self.dp[s][t] = dp_p

            size = len(self.G[s])
            ac_l = [self.e] * (size+1)
            ac_r = [self.e] * (size+1)
            for i, t in enumerate(self.G[s]):
                ac_l[i+1] = self.merge(ac_l[i], self.f(self.dp[s][t], 1))
            for i, t in enumerate(self.G[s][::-1]):
                ac_r[size-i-1] = self.merge(ac_r[size-i], self.f(self.dp[s][t], 1))
            self.ans[s] = self.g(ac_l[size], 0)
            for i, t in enumerate(self.G[s]):
                if t == par:
                    continue
                q.append((t, self.g(self.merge(ac_l[i], ac_r[i+1]), 0)))


def solve():
    N, M = map(int, input().split())
    
    merge = lambda x,y:(x*y)%M
    f = lambda x,y:x+y
    g = lambda x,y:x+y
    e = 1
    tree = Reroot(N, e, merge, f, g)

    for _ in range(N-1):
        a, b = map(int, input().split())
        tree.add_edge(a, b)
        tree.add_edge(b, a)
    ans = tree.build()
    for i in range(1, N+1):
        print(ans[i])


if __name__ == "__main__":
    solve()

Solution (Python):
from collections import defaultdict
from operator import add, mul
import sys
input=sys.stdin.readline


class Reroot:
    def __init__(self, N, M):
        self.G = defaultdict(list)
        self.parents = [-1]*(N+1)
        self.dp = defaultdict(lambda: defaultdict(int))
        self.ans = [0]*(N+1)
        self.merge = lambda x,y:mul(x, y)
        self.add_root = lambda x:x
        self.e = 1
        self.M = M

    def add_edge(self, s, t):
        self.G[s].append(t)

    def build(self):
        self.dfs1(1)
        self.dfs2(1)
        return self.ans

    def dfs1(self, s):
        l = []
        q = [1]
        while q:
            s = q.pop()
            l.append(s)
            for t in self.G[s]:
                if t == self.parents[s]:
                    continue
                self.parents[t] = s
                q.append(t)

        for s in l[::-1]:
            v = self.e
            for t in self.G[s]:
                if t == self.parents[s]:
                    continue
                v = self.merge(v, self.dp[s][t]+1)
            self.dp[self.parents[s]][s] = self.add_root(v)

    def dfs2(self, s):
        q = [(s, self.e)]
        while q:
            s, dp_p = q.pop()
            par = self.parents[s]
            for t in self.G[s]:
                if t == par:
                    self.dp[s][t] = dp_p

            size = len(self.G[s])
            ac_l = [self.e] * (size+1)
            ac_r = [self.e] * (size+1)
            for i, t in enumerate(self.G[s]):
                ac_l[i+1] = self.merge(ac_l[i], self.dp[s][t]+1)%self.M
            for i, t in enumerate(self.G[s][::-1]):
                ac_r[size-i-1] = self.merge(ac_r[size-i], self.dp[s][t]+1)%self.M
            self.ans[s] = self.add_root(ac_l[size])
            for i, t in enumerate(self.G[s]):
                if t == par:
                    continue
                q.append((t, self.add_root(self.merge(ac_l[i], ac_r[i+1])%self.M)))


def solve():
    N, M = map(int, input().split())
    tree = Reroot(N, M)
    for _ in range(N-1):
        a, b = map(int, input().split())
        tree.add_edge(a, b)
        tree.add_edge(b, a)
    ans = tree.build()
    for i in range(1, N+1):
        print(ans[i])


if __name__ == "__main__":
    solve()

Solution (Python):
from collections import defaultdict
from operator import add, mul
import sys
sys.setrecursionlimit(1000000)


d = defaultdict(list)
N, M = map(int, input().split())
for _ in range(N-1):
    a, b = map(int, input().split())
    d[a].append(b)
    d[b].append(a)

q = [1]
parents = [-1]*(N+1)
dp = defaultdict(lambda: defaultdict(int))
ans = [0]*(N+1)
merge = lambda x,y:mul(x, y)
add_root = lambda x:x
e = 1


def dfs1(s):
    l = []
    q = [1]
    while q:
        s = q.pop()
        l.append(s)
        for t in d[s]:
            if t==parents[s]:
                continue
            parents[t] = s
            q.append(t)

    for s in l[::-1]:
        v = e
        for t in d[s]:
            if t == parents[s]:
                continue
            v = merge(v, dp[s][t]+1)
        dp[parents[s]][s] = add_root(v)
    


def dfs2(s):
    q = [(s, e)]
    while q:
        s, dp_p = q.pop()
        par = parents[s]
        for t in d[s]:
            if t == par:
                dp[s][t] = dp_p

        size = len(d[s])
        ac_l = [e] * (size+1)
        ac_r = [e] * (size+1)
        for i, t in enumerate(d[s]):
            ac_l[i+1] = merge(ac_l[i], dp[s][t]+1)%M
        for i, t in enumerate(d[s][::-1]):
            ac_r[size-i-1] = merge(ac_r[size-i], dp[s][t]+1)%M
        ans[s] = add_root(ac_l[size])
        for i, t in enumerate(d[s]):
            if t == par:
                continue
            q.append((t, add_root(merge(ac_l[i], ac_r[i+1])%M)))


dfs1(1)
dfs2(1)
for i in range(1, N+1):
    print(ans[i])