Buggy python submission (verdict: Time Limit Exceeded):
#!/usr/bin/env python3
import sys
sys.setrecursionlimit(100000)
a_max = 0
class Node:
    def __init__(self):
        self.edge = []
        self.color = {}
    
    def ap_edge(self,e):
        self.edge.append(e)

    def rm_edge(self,e):
        self.edge.remove(e)
    
    def co_edge(self,n, c):
        self.color[n] = c


def solve(N: int, a: "List[int]", b: "List[int]"):
    nodes = [Node() for _ in range(N)]

    for ai, bi in zip(a,b):
        nodes[ai-1].ap_edge(bi)
        nodes[bi-1].ap_edge(ai)

    # a_max = 0

    def s_node(node_num, prev_c):
        global a_max
        el = nodes[node_num-1].edge

        # print("node_num:{} el:{}".format(node_num, el))
        if len(el)>0:
            if prev_c not in range(1,len(el)+1):
                c_list = range(1,len(el)+1)
                a_max = max(a_max, len(el))
            else:
                c_list = list(range(1,len(el)+2))
                c_list.pop(prev_c-1)
                a_max = max(a_max, len(el)+1)
            
            # print("c_list:{} prev_c:{}".format(c_list, prev_c))

            for node_n, c_ in zip(el, c_list):
                # 親の頂点に対する処理
                nodes[node_num-1].co_edge(node_n, c_) # 子のエッジの色を持つ
                # 子の頂点に対する処理
                nodes[node_n-1].rm_edge(node_num) # 親のエッジを削除
                s_node(node_n, c_)

    s_node(1,0)

    print(a_max)
    # ans = []
    for ai, bi in zip(a,b):
        if bi in nodes[ai-1].edge:
            ans = (nodes[ai-1].color[bi])
        else:
            ans = (nodes[bi-1].color[ai])
        print(ans)
    # print(max(ans))
    # [print(c_) for c_ in ans]


    return


# Generated by 1.1.6 https://github.com/kyuridenamida/atcoder-tools  (tips: You use the default template now. You can remove this line by using your custom template)
def main():
    def iterate_tokens():
        for line in sys.stdin:
            for word in line.split():
                yield word
    tokens = iterate_tokens()
    N = int(next(tokens))  # type: int
    a = [int()] * (N - 1)  # type: "List[int]"
    b = [int()] * (N - 1)  # type: "List[int]"
    for i in range(N - 1):
        a[i] = int(next(tokens))
        b[i] = int(next(tokens))
    solve(N, a, b)

if __name__ == '__main__':
    main()


Fixed submission:
#!/usr/bin/env python3
import sys
sys.setrecursionlimit(100000)
a_max = 0
class Node:
    def __init__(self):
        self.edge = []
        self.color = {}
    
    def ap_edge(self,e):
        self.edge.append(e)

    def rm_edge(self,e):
        self.edge.remove(e)
    
    def co_edge(self,n, c):
        self.color[n] = c


def solve(N: int, a: "List[int]", b: "List[int]"):
    nodes = [Node() for _ in range(N)]

    for ai, bi in zip(a,b):
        nodes[ai-1].ap_edge(bi)
        nodes[bi-1].ap_edge(ai)

    # a_max = 0

    def s_node(node_num, prev_c):
        global a_max
        el = nodes[node_num-1].edge

        # print("node_num:{} el:{}".format(node_num, el))
        if len(el)>0:
            if prev_c not in range(1,len(el)+1):
                c_list = range(1,len(el)+1)
                a_max = max(a_max, len(el))
            else:
                c_list = list(range(1,len(el)+2))
                c_list.pop(prev_c-1)
                a_max = max(a_max, len(el)+1)
            
            # print("c_list:{} prev_c:{}".format(c_list, prev_c))

            for node_n, c_ in zip(el, c_list):
                # 親の頂点に対する処理
                nodes[node_num-1].co_edge(node_n, c_) # 子のエッジの色を持つ
                # 子の頂点に対する処理
                nodes[node_n-1].rm_edge(node_num) # 親のエッジを削除
                s_node(node_n, c_)

    s_node(1,0)

    print(a_max)
    # ans = []
    for ai, bi in zip(a,b):
        if bi in nodes[ai-1].edge:
            ans = (nodes[ai-1].color[bi])
        else:
            ans = (nodes[bi-1].color[ai])
        print(ans)
    # print(max(ans))
    # [print(c_) for c_ in ans]


    return


# Generated by 1.1.6 https://github.com/kyuridenamida/atcoder-tools  (tips: You use the default template now. You can remove this line by using your custom template)
def main():
    def iterate_tokens():
        for line in sys.stdin:
            for word in line.split():
                yield word
    tokens = iterate_tokens()
    N = int(next(tokens))  # type: int
    a = [int()] * (N - 1)  # type: "List[int]"
    b = [int()] * (N - 1)  # type: "List[int]"
    for i in range(N - 1):
        a[i] = int(next(tokens))
        b[i] = int(next(tokens))
    solve(N, a, b)

if __name__ == '__main__':
    main()

Buggy python submission (verdict: Time Limit Exceeded):
#!/usr/bin/env python3
import sys
sys.setrecursionlimit(100000)

class Node:
    def __init__(self, num):
        self.num = num
        self.edge = []
        self.color = {}
    
    def ap_edge(self,e):
        self.edge.append(e)

    def rm_edge(self,e):
        self.edge.remove(e)
    
    def co_edge(self,n, c):
        self.color[n] = c




def solve(N: int, a: "List[int]", b: "List[int]"):
    nodes = [Node(num+1) for num in range(N)]

    for ai, bi in zip(a,b):
        nodes[ai-1].ap_edge(bi)
        nodes[bi-1].ap_edge(ai)

    def s_node(node_num, prev_c):
        el = nodes[node_num-1].edge
        # print("node_num:{} el:{}".format(node_num, el))
        if len(el)>0:
            if prev_c not in range(1,len(el)+1):
                c_list = range(1,len(el)+1)
            else:
                c_list = list(range(1,len(el)+2))
                c_list.pop(prev_c-1)
            
            # print("c_list:{} prev_c:{}".format(c_list, prev_c))

            for node_n, c_ in zip(el, c_list):
                # 親の頂点に対する処理
                nodes[node_num-1].co_edge(node_n, c_) # 子のエッジの色を持つ
                # 子の頂点に対する処理
                nodes[node_n-1].rm_edge(node_num) # 親のエッジを削除
                s_node(node_n, c_)

    s_node(1,0)


    ans = []
    for ai, bi in zip(a,b):
        if bi in nodes[ai-1].edge:
            ans.append(nodes[ai-1].color[bi])
        else:
            ans.append(nodes[bi-1].color[ai])

    print(max(ans))
    [print(c_) for c_ in ans]


    return


# Generated by 1.1.6 https://github.com/kyuridenamida/atcoder-tools  (tips: You use the default template now. You can remove this line by using your custom template)
def main():
    def iterate_tokens():
        for line in sys.stdin:
            for word in line.split():
                yield word
    tokens = iterate_tokens()
    N = int(next(tokens))  # type: int
    a = [int()] * (N - 1)  # type: "List[int]"
    b = [int()] * (N - 1)  # type: "List[int]"
    for i in range(N - 1):
        a[i] = int(next(tokens))
        b[i] = int(next(tokens))
    solve(N, a, b)

if __name__ == '__main__':
    main()


Fixed submission:
#!/usr/bin/env python3
import sys
sys.setrecursionlimit(100000)
a_max = 0
class Node:
    def __init__(self):
        self.edge = []
        self.color = {}
    
    def ap_edge(self,e):
        self.edge.append(e)

    def rm_edge(self,e):
        self.edge.remove(e)
    
    def co_edge(self,n, c):
        self.color[n] = c


def solve(N: int, a: "List[int]", b: "List[int]"):
    nodes = [Node() for _ in range(N)]

    for ai, bi in zip(a,b):
        nodes[ai-1].ap_edge(bi)
        nodes[bi-1].ap_edge(ai)

    # a_max = 0

    def s_node(node_num, prev_c):
        global a_max
        el = nodes[node_num-1].edge

        # print("node_num:{} el:{}".format(node_num, el))
        if len(el)>0:
            if prev_c not in range(1,len(el)+1):
                c_list = range(1,len(el)+1)
                a_max = max(a_max, len(el))
            else:
                c_list = list(range(1,len(el)+2))
                c_list.pop(prev_c-1)
                a_max = max(a_max, len(el)+1)
            
            # print("c_list:{} prev_c:{}".format(c_list, prev_c))

            for node_n, c_ in zip(el, c_list):
                # 親の頂点に対する処理
                nodes[node_num-1].co_edge(node_n, c_) # 子のエッジの色を持つ
                # 子の頂点に対する処理
                nodes[node_n-1].rm_edge(node_num) # 親のエッジを削除
                s_node(node_n, c_)

    s_node(1,0)

    print(a_max)
    # ans = []
    for ai, bi in zip(a,b):
        if bi in nodes[ai-1].edge:
            ans = (nodes[ai-1].color[bi])
        else:
            ans = (nodes[bi-1].color[ai])
        print(ans)
    # print(max(ans))
    # [print(c_) for c_ in ans]


    return


# Generated by 1.1.6 https://github.com/kyuridenamida/atcoder-tools  (tips: You use the default template now. You can remove this line by using your custom template)
def main():
    def iterate_tokens():
        for line in sys.stdin:
            for word in line.split():
                yield word
    tokens = iterate_tokens()
    N = int(next(tokens))  # type: int
    a = [int()] * (N - 1)  # type: "List[int]"
    b = [int()] * (N - 1)  # type: "List[int]"
    for i in range(N - 1):
        a[i] = int(next(tokens))
        b[i] = int(next(tokens))
    solve(N, a, b)

if __name__ == '__main__':
    main()

Buggy python submission (verdict: Runtime Error):
#!/usr/bin/env python3
import sys

class Node:
    def __init__(self, num):
        self.num = num
        self.edge = []
        self.color = {}
    
    def ap_edge(self,e):
        self.edge.append(e)

    def rm_edge(self,e):
        self.edge.remove(e)
    
    def co_edge(self,n, c):
        self.color[n] = c




def solve(N: int, a: "List[int]", b: "List[int]"):
    nodes = [Node(num+1) for num in range(N)]

    for ai, bi in zip(a,b):
        nodes[ai-1].ap_edge(bi)
        nodes[bi-1].ap_edge(ai)

    def s_node(node_num, prev_c):
        el = nodes[node_num-1].edge
        # print("node_num:{} el:{}".format(node_num, el))
        if len(el)>0:
            if prev_c not in range(1,len(el)+1):
                c_list = range(1,len(el)+1)
            else:
                c_list = list(range(1,len(el)+2))
                c_list.pop(prev_c-1)
            
            # print("c_list:{} prev_c:{}".format(c_list, prev_c))

            for node_n, c_ in zip(el, c_list):
                # 親の頂点に対する処理
                nodes[node_num-1].co_edge(node_n, c_) # 子のエッジの色を持つ
                # 子の頂点に対する処理
                nodes[node_n-1].rm_edge(node_num) # 親のエッジを削除
                s_node(node_n, c_)

    s_node(1,0)


    ans = []
    for ai, bi in zip(a,b):
        if bi in nodes[ai-1].edge:
            ans.append(nodes[ai-1].color[bi])
        elif ai in nodes[bi-1].edge:
            ans.append(nodes[bi-1].color[ai])
        else:
            ans.append(0)
        

    print(max(ans))
    [print(c_) for c_ in ans]


    return


# Generated by 1.1.6 https://github.com/kyuridenamida/atcoder-tools  (tips: You use the default template now. You can remove this line by using your custom template)
def main():
    def iterate_tokens():
        for line in sys.stdin:
            for word in line.split():
                yield word
    tokens = iterate_tokens()
    N = int(next(tokens))  # type: int
    a = [int()] * (N - 1)  # type: "List[int]"
    b = [int()] * (N - 1)  # type: "List[int]"
    for i in range(N - 1):
        a[i] = int(next(tokens))
        b[i] = int(next(tokens))
    solve(N, a, b)

if __name__ == '__main__':
    main()


Fixed submission:
#!/usr/bin/env python3
import sys
sys.setrecursionlimit(100000)
a_max = 0
class Node:
    def __init__(self):
        self.edge = []
        self.color = {}
    
    def ap_edge(self,e):
        self.edge.append(e)

    def rm_edge(self,e):
        self.edge.remove(e)
    
    def co_edge(self,n, c):
        self.color[n] = c


def solve(N: int, a: "List[int]", b: "List[int]"):
    nodes = [Node() for _ in range(N)]

    for ai, bi in zip(a,b):
        nodes[ai-1].ap_edge(bi)
        nodes[bi-1].ap_edge(ai)

    # a_max = 0

    def s_node(node_num, prev_c):
        global a_max
        el = nodes[node_num-1].edge

        # print("node_num:{} el:{}".format(node_num, el))
        if len(el)>0:
            if prev_c not in range(1,len(el)+1):
                c_list = range(1,len(el)+1)
                a_max = max(a_max, len(el))
            else:
                c_list = list(range(1,len(el)+2))
                c_list.pop(prev_c-1)
                a_max = max(a_max, len(el)+1)
            
            # print("c_list:{} prev_c:{}".format(c_list, prev_c))

            for node_n, c_ in zip(el, c_list):
                # 親の頂点に対する処理
                nodes[node_num-1].co_edge(node_n, c_) # 子のエッジの色を持つ
                # 子の頂点に対する処理
                nodes[node_n-1].rm_edge(node_num) # 親のエッジを削除
                s_node(node_n, c_)

    s_node(1,0)

    print(a_max)
    # ans = []
    for ai, bi in zip(a,b):
        if bi in nodes[ai-1].edge:
            ans = (nodes[ai-1].color[bi])
        else:
            ans = (nodes[bi-1].color[ai])
        print(ans)
    # print(max(ans))
    # [print(c_) for c_ in ans]


    return


# Generated by 1.1.6 https://github.com/kyuridenamida/atcoder-tools  (tips: You use the default template now. You can remove this line by using your custom template)
def main():
    def iterate_tokens():
        for line in sys.stdin:
            for word in line.split():
                yield word
    tokens = iterate_tokens()
    N = int(next(tokens))  # type: int
    a = [int()] * (N - 1)  # type: "List[int]"
    b = [int()] * (N - 1)  # type: "List[int]"
    for i in range(N - 1):
        a[i] = int(next(tokens))
        b[i] = int(next(tokens))
    solve(N, a, b)

if __name__ == '__main__':
    main()

Buggy python submission (verdict: Runtime Error):
#!/usr/bin/env python3
import sys

class Node:
    def __init__(self, num):
        self.num = num
        self.edge = []
        self.color = {}
    
    def ap_edge(self,e):
        self.edge.append(e)

    def rm_edge(self,e):
        self.edge.remove(e)
    
    def co_edge(self,n, c):
        self.color[n] = c




def solve(N: int, a: "List[int]", b: "List[int]"):
    nodes = [Node(num+1) for num in range(N)]

    for ai, bi in zip(a,b):
        nodes[ai-1].ap_edge(bi)
        nodes[bi-1].ap_edge(ai)

    def s_node(node_num, prev_c):
        el = nodes[node_num-1].edge
        # print("node_num:{} el:{}".format(node_num, el))
        if len(el)>0:
            if prev_c not in range(1,len(el)+1):
                c_list = range(1,len(el)+1)
            else:
                c_list = list(range(1,len(el)+2))
                c_list.pop(prev_c-1)
            
            # print("c_list:{} prev_c:{}".format(c_list, prev_c))

            for node_n, c_ in zip(el, c_list):
                # 親の頂点に対する処理
                nodes[node_num-1].co_edge(node_n, c_) # 子のエッジの色を持つ
                # 子の頂点に対する処理
                nodes[node_n-1].rm_edge(node_num) # 親のエッジを削除
                s_node(node_n, c_)

    s_node(1,0)


    ans = []
    for ai, bi in zip(a,b):
        if bi in nodes[ai-1].edge:
            ans.append(nodes[ai-1].color[bi])
        else:
            ans.append(nodes[bi-1].color[ai])
        

    print(max(ans))
    [print(c_) for c_ in ans]


    return


# Generated by 1.1.6 https://github.com/kyuridenamida/atcoder-tools  (tips: You use the default template now. You can remove this line by using your custom template)
def main():
    def iterate_tokens():
        for line in sys.stdin:
            for word in line.split():
                yield word
    tokens = iterate_tokens()
    N = int(next(tokens))  # type: int
    a = [int()] * (N - 1)  # type: "List[int]"
    b = [int()] * (N - 1)  # type: "List[int]"
    for i in range(N - 1):
        a[i] = int(next(tokens))
        b[i] = int(next(tokens))
    solve(N, a, b)

if __name__ == '__main__':
    main()


Fixed submission:
#!/usr/bin/env python3
import sys
sys.setrecursionlimit(100000)
a_max = 0
class Node:
    def __init__(self):
        self.edge = []
        self.color = {}
    
    def ap_edge(self,e):
        self.edge.append(e)

    def rm_edge(self,e):
        self.edge.remove(e)
    
    def co_edge(self,n, c):
        self.color[n] = c


def solve(N: int, a: "List[int]", b: "List[int]"):
    nodes = [Node() for _ in range(N)]

    for ai, bi in zip(a,b):
        nodes[ai-1].ap_edge(bi)
        nodes[bi-1].ap_edge(ai)

    # a_max = 0

    def s_node(node_num, prev_c):
        global a_max
        el = nodes[node_num-1].edge

        # print("node_num:{} el:{}".format(node_num, el))
        if len(el)>0:
            if prev_c not in range(1,len(el)+1):
                c_list = range(1,len(el)+1)
                a_max = max(a_max, len(el))
            else:
                c_list = list(range(1,len(el)+2))
                c_list.pop(prev_c-1)
                a_max = max(a_max, len(el)+1)
            
            # print("c_list:{} prev_c:{}".format(c_list, prev_c))

            for node_n, c_ in zip(el, c_list):
                # 親の頂点に対する処理
                nodes[node_num-1].co_edge(node_n, c_) # 子のエッジの色を持つ
                # 子の頂点に対する処理
                nodes[node_n-1].rm_edge(node_num) # 親のエッジを削除
                s_node(node_n, c_)

    s_node(1,0)

    print(a_max)
    # ans = []
    for ai, bi in zip(a,b):
        if bi in nodes[ai-1].edge:
            ans = (nodes[ai-1].color[bi])
        else:
            ans = (nodes[bi-1].color[ai])
        print(ans)
    # print(max(ans))
    # [print(c_) for c_ in ans]


    return


# Generated by 1.1.6 https://github.com/kyuridenamida/atcoder-tools  (tips: You use the default template now. You can remove this line by using your custom template)
def main():
    def iterate_tokens():
        for line in sys.stdin:
            for word in line.split():
                yield word
    tokens = iterate_tokens()
    N = int(next(tokens))  # type: int
    a = [int()] * (N - 1)  # type: "List[int]"
    b = [int()] * (N - 1)  # type: "List[int]"
    for i in range(N - 1):
        a[i] = int(next(tokens))
        b[i] = int(next(tokens))
    solve(N, a, b)

if __name__ == '__main__':
    main()

Buggy python submission (verdict: Runtime Error):
#!/usr/bin/env python3
import sys

class Node:
    def __init__(self, num):
        self.num = num
        self.edge = []
        self.color = {}
    
    def ap_edge(self,e):
        self.edge.append(e)

    def rm_edge(self,e):
        self.edge.remove(e)
    
    def co_edge(self,n, c):
        self.color[n] = c




def solve(N: int, a: "List[int]", b: "List[int]"):
    nodes = [Node(num+1) for num in range(N)]

    for ai, bi in zip(a,b):
        nodes[ai-1].ap_edge(bi)
        nodes[bi-1].ap_edge(ai)

    def s_node(node_num, prev_c):
        el = nodes[node_num-1].edge
        # print("node_num:{} el:{}".format(node_num, el))
        if len(el)>0:
            if prev_c not in list(range(1,len(el)+1)):
                c_list = list(range(1,len(el)+1))
            else:
                c_list = list(range(1,len(el)+2))
                c_list.pop(prev_c-1)
            
            if len(c_list) != len(el):
                print("error")
            # print("c_list:{} prev_c:{}".format(c_list, prev_c))

            for node_n, c_ in zip(el, c_list):
                # 親の頂点に対する処理
                nodes[node_num-1].co_edge(node_n, c_) # 子のエッジの色を持つ
                # 子の頂点に対する処理
                nodes[node_n-1].rm_edge(node_num) # 親のエッジを削除
                s_node(node_n, c_)

    s_node(1,0)


    ans = []
    for ai, bi in zip(a,b):
        if bi in nodes[ai-1].edge:
            ans.append(nodes[ai-1].color[bi])
        else:
            ans.append(nodes[bi-1].color[ai])
        

    print(max(ans))
    [print(c_) for c_ in ans]


    return


# Generated by 1.1.6 https://github.com/kyuridenamida/atcoder-tools  (tips: You use the default template now. You can remove this line by using your custom template)
def main():
    def iterate_tokens():
        for line in sys.stdin:
            for word in line.split():
                yield word
    tokens = iterate_tokens()
    N = int(next(tokens))  # type: int
    a = [int()] * (N - 1)  # type: "List[int]"
    b = [int()] * (N - 1)  # type: "List[int]"
    for i in range(N - 1):
        a[i] = int(next(tokens))
        b[i] = int(next(tokens))
    solve(N, a, b)

if __name__ == '__main__':
    main()


Fixed submission:
#!/usr/bin/env python3
import sys
sys.setrecursionlimit(100000)
a_max = 0
class Node:
    def __init__(self):
        self.edge = []
        self.color = {}
    
    def ap_edge(self,e):
        self.edge.append(e)

    def rm_edge(self,e):
        self.edge.remove(e)
    
    def co_edge(self,n, c):
        self.color[n] = c


def solve(N: int, a: "List[int]", b: "List[int]"):
    nodes = [Node() for _ in range(N)]

    for ai, bi in zip(a,b):
        nodes[ai-1].ap_edge(bi)
        nodes[bi-1].ap_edge(ai)

    # a_max = 0

    def s_node(node_num, prev_c):
        global a_max
        el = nodes[node_num-1].edge

        # print("node_num:{} el:{}".format(node_num, el))
        if len(el)>0:
            if prev_c not in range(1,len(el)+1):
                c_list = range(1,len(el)+1)
                a_max = max(a_max, len(el))
            else:
                c_list = list(range(1,len(el)+2))
                c_list.pop(prev_c-1)
                a_max = max(a_max, len(el)+1)
            
            # print("c_list:{} prev_c:{}".format(c_list, prev_c))

            for node_n, c_ in zip(el, c_list):
                # 親の頂点に対する処理
                nodes[node_num-1].co_edge(node_n, c_) # 子のエッジの色を持つ
                # 子の頂点に対する処理
                nodes[node_n-1].rm_edge(node_num) # 親のエッジを削除
                s_node(node_n, c_)

    s_node(1,0)

    print(a_max)
    # ans = []
    for ai, bi in zip(a,b):
        if bi in nodes[ai-1].edge:
            ans = (nodes[ai-1].color[bi])
        else:
            ans = (nodes[bi-1].color[ai])
        print(ans)
    # print(max(ans))
    # [print(c_) for c_ in ans]


    return


# Generated by 1.1.6 https://github.com/kyuridenamida/atcoder-tools  (tips: You use the default template now. You can remove this line by using your custom template)
def main():
    def iterate_tokens():
        for line in sys.stdin:
            for word in line.split():
                yield word
    tokens = iterate_tokens()
    N = int(next(tokens))  # type: int
    a = [int()] * (N - 1)  # type: "List[int]"
    b = [int()] * (N - 1)  # type: "List[int]"
    for i in range(N - 1):
        a[i] = int(next(tokens))
        b[i] = int(next(tokens))
    solve(N, a, b)

if __name__ == '__main__':
    main()

Buggy python submission (verdict: Runtime Error):
#!/usr/bin/env python3
import sys

class Node:
    def __init__(self, num):
        self.num = num
        self.edge = []
        self.color = {}
    
    def ap_edge(self,e):
        self.edge.append(e)

    def rm_edge(self,e):
        self.edge.remove(e)
    
    def co_edge(self,n, c):
        self.color[n] = c




def solve(N: int, a: "List[int]", b: "List[int]"):
    nodes = [Node(num+1) for num in range(N)]

    for ai, bi in zip(a,b):
        nodes[ai-1].ap_edge(bi)
        nodes[bi-1].ap_edge(ai)

    def s_node(node_num, prev_c):
        el = nodes[node_num-1].edge
        # print("node_num:{} el:{}".format(node_num, el))
        
        if prev_c not in list(range(1,len(el)+1)):
            c_list = list(range(1,len(el)+1))
        else:
            c_list = list(range(1,len(el)+2))
            c_list.pop(prev_c-1)
        
        if len(c_list) != len(el):
            print("error")
        # print("c_list:{} prev_c:{}".format(c_list, prev_c))

        for node_n, c_ in zip(el, c_list):
            # 親の頂点に対する処理
            nodes[node_num-1].co_edge(node_n, c_) # 子のエッジの色を持つ
            # 子の頂点に対する処理
            nodes[node_n-1].rm_edge(node_num) # 親のエッジを削除
            s_node(node_n, c_)

    s_node(1,0)


    ans = []
    for ai, bi in zip(a,b):
        if bi in nodes[ai-1].edge:
            ans.append(nodes[ai-1].color[bi])
        else:
            ans.append(nodes[bi-1].color[ai])
        

    print(max(ans))
    [print(c_) for c_ in ans]


    return


# Generated by 1.1.6 https://github.com/kyuridenamida/atcoder-tools  (tips: You use the default template now. You can remove this line by using your custom template)
def main():
    def iterate_tokens():
        for line in sys.stdin:
            for word in line.split():
                yield word
    tokens = iterate_tokens()
    N = int(next(tokens))  # type: int
    a = [int()] * (N - 1)  # type: "List[int]"
    b = [int()] * (N - 1)  # type: "List[int]"
    for i in range(N - 1):
        a[i] = int(next(tokens))
        b[i] = int(next(tokens))
    solve(N, a, b)

if __name__ == '__main__':
    main()


Fixed submission:
#!/usr/bin/env python3
import sys
sys.setrecursionlimit(100000)
a_max = 0
class Node:
    def __init__(self):
        self.edge = []
        self.color = {}
    
    def ap_edge(self,e):
        self.edge.append(e)

    def rm_edge(self,e):
        self.edge.remove(e)
    
    def co_edge(self,n, c):
        self.color[n] = c


def solve(N: int, a: "List[int]", b: "List[int]"):
    nodes = [Node() for _ in range(N)]

    for ai, bi in zip(a,b):
        nodes[ai-1].ap_edge(bi)
        nodes[bi-1].ap_edge(ai)

    # a_max = 0

    def s_node(node_num, prev_c):
        global a_max
        el = nodes[node_num-1].edge

        # print("node_num:{} el:{}".format(node_num, el))
        if len(el)>0:
            if prev_c not in range(1,len(el)+1):
                c_list = range(1,len(el)+1)
                a_max = max(a_max, len(el))
            else:
                c_list = list(range(1,len(el)+2))
                c_list.pop(prev_c-1)
                a_max = max(a_max, len(el)+1)
            
            # print("c_list:{} prev_c:{}".format(c_list, prev_c))

            for node_n, c_ in zip(el, c_list):
                # 親の頂点に対する処理
                nodes[node_num-1].co_edge(node_n, c_) # 子のエッジの色を持つ
                # 子の頂点に対する処理
                nodes[node_n-1].rm_edge(node_num) # 親のエッジを削除
                s_node(node_n, c_)

    s_node(1,0)

    print(a_max)
    # ans = []
    for ai, bi in zip(a,b):
        if bi in nodes[ai-1].edge:
            ans = (nodes[ai-1].color[bi])
        else:
            ans = (nodes[bi-1].color[ai])
        print(ans)
    # print(max(ans))
    # [print(c_) for c_ in ans]


    return


# Generated by 1.1.6 https://github.com/kyuridenamida/atcoder-tools  (tips: You use the default template now. You can remove this line by using your custom template)
def main():
    def iterate_tokens():
        for line in sys.stdin:
            for word in line.split():
                yield word
    tokens = iterate_tokens()
    N = int(next(tokens))  # type: int
    a = [int()] * (N - 1)  # type: "List[int]"
    b = [int()] * (N - 1)  # type: "List[int]"
    for i in range(N - 1):
        a[i] = int(next(tokens))
        b[i] = int(next(tokens))
    solve(N, a, b)

if __name__ == '__main__':
    main()