Buggy python submission (verdict: Runtime Error):
# coding: utf-8


def solve(*args: str) -> str:
    n = int(args[0])

    link = {}
    edge = []

    for i, ab in enumerate(args[1:]):
        a, b = sorted(map(int, ab.split()))
        edge.append((a, b))
        if a in link:
            link[a].append(b)
        else:
            link[a] = [b]

        if b in link:
            link[b].append(a)
        else:
            link[b] = [a]

    n_color = len(max(link.items(), key=lambda x: len(x[1]))[1])

    color = {}
    seek(1, 0, color, link)

    return str(n_color) + '\n' \
        + '\n'.join(map(str, (color[ab] for ab in edge)))


def seek(i: int, parent: int, color: dict, link: dict):
    c = 1
    inlet = tuple(sorted((i, parent)))
    for node in link[i]:
        if node == parent:
            continue

        if 0 < parent and c == color[inlet]:
            c += 1
        color[tuple(sorted((i, node)))] = c
        c += 1
        seek(node, i, color, link)


if __name__ == "__main__":
    print(solve(*(open(0).read().splitlines())))


Fixed submission:
# coding: utf-8


def solve(*args: str) -> str:
    n = int(args[0])

    link = [set() for _ in range(n+1)]
    edge = []

    for i, ab in enumerate(args[1:]):
        a, b = sorted(map(int, ab.split()))
        edge.append((a, b))
        link[a].add(b)
        link[b].add(a)

    n_color = max(map(len, link))

    color = {}

    queue = [(0, 1)]

    while queue:
        parent, cur = queue.pop()
        used = color[tuple(sorted((parent, cur)))] if 0 < parent else 0
        c = 1

        for child in link[cur]:
            if child == parent:
                continue

            if c == used:
                c += 1
            color[tuple(sorted((cur, child)))] = c
            c += 1

            queue.append((cur, child))

    return str(n_color) + '\n' \
        + '\n'.join(map(str, (color[ab] for ab in edge)))


if __name__ == "__main__":
    print(solve(*(open(0).read().splitlines())))

Buggy python submission (verdict: Runtime Error):
# coding: utf-8


def solve(*args: str) -> str:
    n = int(args[0])

    link = {}
    for ab in args[1:]:
        a, b = map(int, ab.split())
        if a in link:
            link[a].append(b)
        else:
            link[a] = [b]
        if b in link:
            link[b].append(a)
        else:
            link[b] = [a]

    n_color = len(max(link.items(), key=lambda x: len(x[1]))[1])

    color = [0]*n

    color[0] = 1
    seek(1, 0, color, link)

    return str(n_color) + '\n' + '\n'.join(map(str, color[:-1]))


def seek(i: int, parent: int, color: list, link: dict):
    c = 1
    for node in link[i]:
        if node == parent:
            continue

        if c == color[i-1]:
            c += 1
        color[node-1] = c
        c += 1
        seek(node, i, color, link)


if __name__ == "__main__":
    print(solve(*(open(0).read().splitlines())))


Fixed submission:
# coding: utf-8


def solve(*args: str) -> str:
    n = int(args[0])

    link = [set() for _ in range(n+1)]
    edge = []

    for i, ab in enumerate(args[1:]):
        a, b = sorted(map(int, ab.split()))
        edge.append((a, b))
        link[a].add(b)
        link[b].add(a)

    n_color = max(map(len, link))

    color = {}

    queue = [(0, 1)]

    while queue:
        parent, cur = queue.pop()
        used = color[tuple(sorted((parent, cur)))] if 0 < parent else 0
        c = 1

        for child in link[cur]:
            if child == parent:
                continue

            if c == used:
                c += 1
            color[tuple(sorted((cur, child)))] = c
            c += 1

            queue.append((cur, child))

    return str(n_color) + '\n' \
        + '\n'.join(map(str, (color[ab] for ab in edge)))


if __name__ == "__main__":
    print(solve(*(open(0).read().splitlines())))

Buggy python submission (verdict: Runtime Error):
# coding: utf-8


def solve(*args: str) -> str:
    n = int(args[0])

    link = {}
    for ab in args[1:]:
        a, b = map(int, ab.split())
        if a in link:
            link[a].append(b)
        else:
            link[a] = [b]
        if b in link:
            link[b].append(a)
        else:
            link[b] = [a]

    color = [0]*n

    color[0] = 1
    seek(1, 0, color, link)

    return '\n'.join(map(str, color))


def seek(i: int, parent: int, color: list, link: dict):
    c = 1
    for node in link[i]:
        if node == parent:
            continue

        if c == color[i-1]:
            c += 1
        color[node-1] = c
        c += 1
        seek(node, i, color, link)


if __name__ == "__main__":
    print(solve(*(open(0).read().splitlines())))


Fixed submission:
# coding: utf-8


def solve(*args: str) -> str:
    n = int(args[0])

    link = [set() for _ in range(n+1)]
    edge = []

    for i, ab in enumerate(args[1:]):
        a, b = sorted(map(int, ab.split()))
        edge.append((a, b))
        link[a].add(b)
        link[b].add(a)

    n_color = max(map(len, link))

    color = {}

    queue = [(0, 1)]

    while queue:
        parent, cur = queue.pop()
        used = color[tuple(sorted((parent, cur)))] if 0 < parent else 0
        c = 1

        for child in link[cur]:
            if child == parent:
                continue

            if c == used:
                c += 1
            color[tuple(sorted((cur, child)))] = c
            c += 1

            queue.append((cur, child))

    return str(n_color) + '\n' \
        + '\n'.join(map(str, (color[ab] for ab in edge)))


if __name__ == "__main__":
    print(solve(*(open(0).read().splitlines())))