CodeEff/ECCO huggingface dataset:
# Original solution
import sys
from collections import deque
input = sys.stdin.readline
N = int(eval(input()))
bi=[0]* N
children = [[] for _ in range(N)]
for i in range(N-1):
    a, b = list(map(int, input().split()))
    bi[i]=b-1
    children[a-1].append(b-1)

queue = deque([0])
colors = [0] * N
maxColor = 0
while queue:
    node = queue.popleft()
    nodeColor = colors[node]
    color = 1
    for child in children[node]:
        if color == nodeColor: color += 1
        colors[child] = color
        queue.append(child)
        color += 1
    maxColor = max(maxColor, color-1)

print(maxColor)
for i in range(N-1):
    print((colors[bi[i]]))

# Optimized solution
import sys
from collections import deque
input = sys.stdin.readline
N = int(eval(input()))
bi=[0]* N
children = [[] for _ in range(N)]
for i in range(N-1):
    a, b = list(map(int, input().split()))
    bi[i]=b-1
    children[a-1].append(bi[i])

queue = deque([0])
colors = [0] * N
maxColor = 0
while queue:
    node = queue.popleft()
    nodeColor = colors[node]
    color = 1
    for child in children[node]:
        if color == nodeColor: color += 1
        colors[child] = color
        queue.append(child)
        color += 1
    maxColor = max(maxColor, color-1)

print(maxColor)
for i in range(N-1):
    print((colors[bi[i]]))
# Original solution
import sys
from collections import deque
input = sys.stdin.readline
N = int(eval(input()))
bi=[0]* N
children = [[] for _ in range(N)]
for i in range(N-1):
    a, b = list(map(int, input().split()))
    b-=1
    bi[i]=b
    children[a-1].append(b)

queue = deque([0])
colors = [0] * N
maxColor = 0
while queue:
    node = queue.popleft()
    nodeColor = colors[node]
    color = 1
    for child in children[node]:
        if color == nodeColor: color += 1
        colors[child] = color
        queue.append(child)
        color += 1
    maxColor = max(maxColor, color-1)

print(maxColor)
for i in range(N-1):
    print((colors[bi[i]]))

# Optimized solution
import sys
from collections import deque
input = sys.stdin.readline
N = int(eval(input()))
bi=[0]* N
children = [[] for _ in range(N)]
for i in range(N-1):
    a, b = list(map(int, input().split()))
    b-=1
    bi[i]=b
    children[a-1].append(b)

queue = deque([0])
colors = [0] * N
#maxColor = 0
while queue:
    node = queue.popleft()
    nodeColor = colors[node]
    color = 1
    for child in children[node]:
        if color == nodeColor: color += 1
        colors[child] = color
        queue.append(child)
        color += 1
    #maxColor = max(maxColor, color-1)

print((max(colors)))
for i in range(N-1):
    print((colors[bi[i]]))
# Original solution
import queue

N = int(eval(input()))
ab = []
deg = [0 for i in range(N)]
child = [[] for _ in range(N)]
edge = {}
color = [0 for _ in range(N-1)]
for i in range(N-1):
  tmp = list(map(int, input().split()))
  deg[tmp[0]-1] += 1
  deg[tmp[1]-1] += 1
 
  child[tmp[0]-1].append(tmp[1]-1)
  child[tmp[1]-1].append(tmp[0]-1)
  tmp = [tmp[0]-1, tmp[1]-1]
  edge[tuple(tmp)] = i
  
q = queue.Queue()
q.put([None, 0, None])
used = [0]
# parent, self, color
while not q.empty():
  current = q.get()
  if current[0] is not None:
    cnt = 1
    for c in child[current[1]]:
      if c in used:
        continue
      used.append(c)
      if cnt == current[2]:
        cnt += 1
      q.put([current[1], c, cnt])
      ind = [current[1], c] if current[1] < c else [c, current[1]]
      
      color[edge[tuple(ind)]] = cnt
      
      cnt += 1
  else:
    for i, c in enumerate(child[current[1]]):
      used.append(c)
      q.put([current[1], c, i+1])
      ind = [current[1], c] if current[1] < c else [c, current[1]]
      #print(edge[tuple(ind)], i+1)
      color[edge[tuple(ind)]] = i+1
print((max(deg)))
for c in color:
  print(c)

# Optimized solution
import queue

N = int(eval(input()))
ab = []
deg = [0 for i in range(N)]
child = [[] for _ in range(N)]
edge = {}
color = [0 for _ in range(N-1)]
for i in range(N-1):
  tmp = list(map(int, input().split()))
  deg[tmp[0]-1] += 1
  deg[tmp[1]-1] += 1
 
  child[tmp[0]-1].append(tmp[1]-1)
  child[tmp[1]-1].append(tmp[0]-1)
  tmp = [tmp[0]-1, tmp[1]-1]
  edge[tuple(tmp)] = i
  
q = queue.Queue()
q.put([None, 0, None])
used = [0]
# parent, self, color
while not q.empty():
  current = q.get()
  if current[0] is not None:
    cnt = 1
    for c in child[current[1]]:
  #    if c in used:
  #      continue
      used.append(c)
      if cnt == current[2]:
        cnt += 1
      q.put([current[1], c, cnt])
      ind = [current[1], c] if current[1] < c else [c, current[1]]
      
      color[edge[tuple(ind)]] = cnt
      child[c].remove(current[1])
      cnt += 1
  else:
    for i, c in enumerate(child[current[1]]):
      used.append(c)
      q.put([current[1], c, i+1])
      ind = [current[1], c] if current[1] < c else [c, current[1]]
      #print(edge[tuple(ind)], i+1)
      color[edge[tuple(ind)]] = i+1
      child[c].remove(current[1])

print((max(deg)))
for c in color:
  print(c)
# Original solution
from collections import deque

N = int(input())
# mtx = np.zeros([N, N], dtype=np.int32)
tree = [[] for i in range(N)]

key_order = [0] * (N-1)
for i in range(N-1):
    in1, in2 = map(int, input().split())
    in1 -= 1
    in2 -= 1
    tree[in1].append(in2)
    tree[in2].append(in1)

    key_order[i] = (in1, in2)

# [print(i, t) for i, t in enumerate(tree)]


def bfs(tree, p):
    seen = [False] * len(tree)
    queue = deque((p,))

    node_colors = [set() for _ in tree]
    edge_colors = dict()
    all_colors = set()
    color = 0

    while len(queue) > 0:
        q = queue.popleft()
        seen[q] = True
        for v in tree[q]:
            if not seen[v]:
                residual = all_colors - node_colors[q]
                if len(residual) > 0:
                    this_color = residual.pop()
                else:
                    color += 1
                    this_color = color
                edge_colors[(q, v)] = this_color
                node_colors[q].add(this_color)
                node_colors[v].add(this_color)
                all_colors.add(this_color)

                queue.append(v)

    return edge_colors


edge_colors = bfs(tree, 0)

print(max([c for key, c in edge_colors.items()]))
[print(edge_colors[t]) for t in key_order]
# print(edge_colors)

# show_tree(tree)


# Optimized solution
from collections import deque

N = int(input())
# mtx = np.zeros([N, N], dtype=np.int32)
tree = [[] for i in range(N)]

key_order = [0] * (N-1)
for i in range(N-1):
    in1, in2 = map(int, input().split())
    in1 -= 1
    in2 -= 1
    tree[in1].append(in2)
    tree[in2].append(in1)

    key_order[i] = (in1, in2)

# [print(i, t) for i, t in enumerate(tree)]


def bfs(tree, p):
    seen = [False] * len(tree)
    queue = deque((p,))

    edge_colors = dict()
    node_colors = [0] * len(tree)
    while len(queue) > 0:
        q = queue.popleft()
        seen[q] = True

        parent_color = node_colors[q]

        cnt = 1
        for v in tree[q]:
            if not seen[v]:
                if cnt == parent_color:
                    cnt += 1

                edge_colors[(q, v)] = cnt
                node_colors[v] = cnt
                queue.append(v)
                cnt += 1



    """
    node_colors = [set() for _ in tree]
    edge_colors = dict()
    all_colors = set()
    color = 0

    while len(queue) > 0:
        q = queue.popleft()
        seen[q] = True

        for v in tree[q]:
            if not seen[v]:
                residual = all_colors - node_colors[q]
                if len(residual) > 0:
                    this_color = residual.pop()
                else:
                    color += 1
                    this_color = color
                edge_colors[(q, v)] = this_color
                node_colors[q].add(this_color)
                node_colors[v].add(this_color)
                all_colors.add(this_color)

                queue.append(v)
    """

    return edge_colors


edge_colors = bfs(tree, 0)

print(max([c for key, c in edge_colors.items()]))
[print(edge_colors[t]) for t in key_order]
# print(edge_colors)

# show_tree(tree)
# Original solution
#!/usr/bin/python3
# -*- coding: utf-8 -*-

import sys
#import bisect
#from collections import deque
import math

sys.setrecursionlimit(10**5)

def input():
    return sys.stdin.readline().rstrip('\n')

N = int(eval(input()))
peer_nodes = [[] for _ in range(N)]
edge_colors = [[0]*(N) for _ in range(N)]
pairs = []
for _ in range(N-1):
    a,b = list(map(int, input().split()))
    a -= 1
    b -= 1
    pairs.append([a,b])
    peer_nodes[a].append(b)
    if not a in peer_nodes[b]:
        peer_nodes[b].append(a)
    edge_colors[a][b] = 0

#print(peer_nodes,edge_colors)

def draw_color_return_max_colors(node):
    max_colors = 0
    peers = peer_nodes[node]
    if len(peers) == 0:
        return 0
    used_colors = []
    for p in peers:
        c = edge_colors[node][p]
        if c != 0:
            used_colors.append(c)
    #print('----', node, peers,used_colors)
    if len(used_colors) == len(peers):
        return 0
    color = 1
    for p in peers:
        #print(node, p, edge_colors[node][p])
        while(color in used_colors):
            color += 1
        if edge_colors[node][p] == 0:
            used_colors.append(color)
            edge_colors[node][p] = color
            edge_colors[p][node] = color
    max_colors = max(used_colors)
    for p in peers:
        max_colors = max(max_colors, draw_color_return_max_colors(p))

    return max_colors


print((draw_color_return_max_colors(pairs[0][0])))

for a,b in pairs:
    print((edge_colors[a][b]))


# Optimized solution
#!/usr/bin/python3
# -*- coding: utf-8 -*-

import sys
#import bisect
#from collections import deque
import math

sys.setrecursionlimit(10**5)

def input():
    return sys.stdin.readline().rstrip('\n')

N = int(eval(input()))
peer_nodes = [[] for _ in range(N)]
edge_colors = [[0]*(N) for _ in range(N)]
pairs = []
for _ in range(N-1):
    a,b = list(map(int, input().split()))
    a -= 1
    b -= 1
    pairs.append([a,b])
    peer_nodes[a].append(b)
    if not a in peer_nodes[b]:
        peer_nodes[b].append(a)
    edge_colors[a][b] = 0

#print(peer_nodes,edge_colors)

def draw_color_return_max_colors(node):
    max_colors = 0
    peers = peer_nodes[node]
    if len(peers) == 0:
        return 0
    used_colors = []
    for p in peers:
        c = edge_colors[node][p]
        if c != 0:
            used_colors.append(c)
    #print('----', node, peers,used_colors)
    if len(used_colors) == len(peers):
        return 0
    color = 1
    for p in peers:
        if edge_colors[node][p] > 0:
            continue
        else:
            while(color in used_colors):
                color += 1
            if edge_colors[node][p] == 0:
                used_colors.append(color)
                edge_colors[node][p] = color
                edge_colors[p][node] = color
    max_colors = max(used_colors)
    for p in peers:
        max_colors = max(max_colors, draw_color_return_max_colors(p))

    return max_colors


print((draw_color_return_max_colors(pairs[0][0])))

for a,b in pairs:
    print((edge_colors[a][b]))
# Original solution
#!/usr/bin/python3
# -*- coding: utf-8 -*-

import sys
#import bisect
#from collections import deque
import math

sys.setrecursionlimit(10**5)

def input():
    return sys.stdin.readline().rstrip('\n')

N = int(eval(input()))
peer_nodes = [[] for _ in range(N)]
edge_colors = [{} for _ in range(N)]
pairs = []
for _ in range(N-1):
    a,b = list(map(int, input().split()))
    a -= 1
    b -= 1
    pairs.append([a,b])
    peer_nodes[a].append(b)
    if not a in peer_nodes[b]:
        peer_nodes[b].append(a)
    edge_colors[a][b] = 0

#print(peer_nodes,edge_colors)

def draw_color_return_max_colors(node):
    max_colors = 0
    peers = peer_nodes[node]
    if len(peers) == 0:
        return 0
    used_colors = []
    for p in peers:
        if node<p:
            i,j = node,p
        else:
            i,j = p,node
        c = edge_colors[i][j]
        if c != 0:
            used_colors.append(c)
    #print('----', node, peers,used_colors)
    if len(used_colors) == len(peers):
        return 0
    color = 1
    for p in peers:
        if node<p:
            i,j = node,p
        else:
            i,j = p,node
        if edge_colors[i][j] > 0:
            continue
        else:
            while(color in used_colors):
                used_colors.remove(color)
                color += 1
            used_colors.append(color)
            edge_colors[i][j] = color
    max_colors = max([color] + used_colors)
    for p in peers:
        max_colors = max(max_colors, draw_color_return_max_colors(p))

    return max_colors


print((draw_color_return_max_colors(pairs[0][0])))

for a,b in pairs:
    print((edge_colors[a][b]))


# Optimized solution
#!/usr/bin/python3
# -*- coding: utf-8 -*-

import sys
#import bisect
#from collections import deque
import math

sys.setrecursionlimit(10**5)

def input():
    return sys.stdin.readline().rstrip('\n')

N = int(eval(input()))
peers = [[] for _ in range(N)]
colors = [{} for _ in range(N)]
pairs = []
for _ in range(N-1):
    a,b = list(map(int, input().split()))
    a -= 1
    b -= 1
    pairs.append([a,b])
    peers[a].append(b)
    colors[a][b] = 0


def draw(node, parent_edge_color):
    _peers = peers[node]
    if len(_peers) == 0:
        return 0
    color = 1
    max_nrof_color = 1
    for peer in _peers:
        #print(node,peer,color)
        if color == parent_edge_color:
            color +=1
        colors[node][peer] = color
        max_nrof_color = max(max_nrof_color, color, draw(peer, color))
        color += 1

    return max_nrof_color


print((draw(0,0)))
for a,b in pairs:
    print((colors[a][b]))
# Original solution
import sys
from collections import deque

read = sys.stdin.read
readline = sys.stdin.readline
readlines = sys.stdin.readlines
sys.setrecursionlimit(10 ** 9)
INF = 1 << 60
MOD = 1000000007


def main():
    N, *AB = list(map(int, read().split()))
    G = [[] for _ in range(N)]
    for i, (a, b) in enumerate(zip(*[iter(AB)] * 2)):
        G[a - 1].append((i, b - 1))
        G[b - 1].append((i, a - 1))

    color = [0] * (N - 1)

    def dfs(v, p, pc):
        c = 1
        for i, nv in G[v]:
            if nv == p:
                continue
            if c == pc:
                c += 1
            color[i] = c
            dfs(nv, v, c)
            c += 1

    dfs(0, -1, 0)

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


if __name__ == '__main__':
    main()


# Optimized solution
import sys
from collections import deque

read = sys.stdin.read
readline = sys.stdin.readline
readlines = sys.stdin.readlines
sys.setrecursionlimit(10 ** 9)
INF = 1 << 60
MOD = 1000000007


def main():
    N, *AB = map(int, read().split())
    G = [[] for _ in range(N)]
    for i, (a, b) in enumerate(zip(*[iter(AB)] * 2)):
        G[a - 1].append((i, b - 1))
        G[b - 1].append((i, a - 1))

    queue = deque([0])
    color = [0] * (N - 1)
    color_from_parent = [0] * N
    color_from_parent[0] = -1

    while queue:
        v = queue.popleft()
        c = 1
        for i, nv in G[v]:
            if color_from_parent[nv] != 0:
                continue
            if c == color_from_parent[v]:
                c += 1
            color_from_parent[nv] = c
            color[i] = c
            c += 1
            queue.append(nv)

    print(max(color))
    print(*color, sep='\n')
    return


if __name__ == '__main__':
    main()
# Original solution
from collections import deque

def main():
    N = int(eval(input()))
    path = [[] for _ in range(N)]
    ab = []
    ans = {}
    visited = [False] * N
    visited[0] = True
    for _ in range(N-1):
        a, b = list(map(int, input().split()))
        path[a-1].append(b-1)
        path[b-1].append(a-1)
        ab.append((a-1, b-1))
    
    que = deque([(0, 0)])
    while que:
        k = 1
        # k = 0
        pre, c = que.popleft()
        for next_node in path[pre]:
            if visited[next_node]:
                continue
            
            if c == k:
                k += 1
            visited[next_node] = True
            ans[(pre, next_node)] = k
            que.append((next_node, k))
            k += 1
            

    print((max(ans.values())))
    for key in ab:
        print((ans[key]))

if __name__ == '__main__':
    main()

# Optimized solution
from collections import deque

def main():
    N = int(eval(input()))
    path = [[] for _ in range(N)]
    ab = []
    ans = {}
    visited = [False] * N
    visited[0] = True
    for _ in range(N-1):
        a, b = list(map(int, input().split()))
        path[a-1].append(b-1)
        # path[b-1].append(a-1)
        ab.append((a-1, b-1))
    
    que = deque([(0, 0)])
    while que:
        k = 1
        pre, c = que.popleft()
        for next_node in path[pre]:
            if visited[next_node]:
                continue
            
            if c == k:
                k += 1
            visited[next_node] = True
            ans[(pre, next_node)] = k
            que.append((next_node, k))
            k += 1
            

    print((max(ans.values())))
    for key in ab:
        print((ans[key]))

if __name__ == '__main__':
    main()
# Original solution
# ABC146 D - Coloring Edges on Tree
from collections import deque

n = int(eval(input()))
E = [[] for _ in range(n + 1)]
edge_order = []

for i in range(n-1):
    a,b=list(map(int,input().split()))
    E[a].append(b)
    edge_order.append(b)

# 頂点1からBFS
q = deque([1])
color = [0] * (n+1) 
while q:
    V = q.popleft()
    c = 1
    for nv in E[V]:
        if c == color[V]:
            c += 1
        color[nv] = c
        c += 1
        q.append(nv)

print((max(color)))
for i in edge_order:
    print((color[i]))



# Optimized solution
n=int(eval(input()))
G=[[] for i in range(n+1)]
G_order=[]
for i in range(n-1):
  a,b=list(map(int,input().split()))
  G[a].append(b)
  G_order.append(b)

from collections import deque
q=deque([1])
color=[0]*(n+1)
while q:
  cur=q.popleft()
  c=1
  for nx in G[cur]:
    if c==color[cur]:
      c+=1
    color[nx]=c
    c+=1
    q.append(nx)

print((max(color)))
for i in G_order:
  print((color[i]))
# Original solution
n=int(eval(input()))
G=[[] for i in range(n+1)]
G_order=[]
for i in range(n-1):
  a,b=list(map(int,input().split()))
  G[a].append(b)
  G_order.append(b)

from collections import deque
q=deque([1])
color=[0]*(n+1)
while q:
  cur=q.popleft()
  c=1
  for nx in G[cur]:
    if c==color[cur]:
      c+=1
    color[nx]=c
    c+=1
    q.append(nx)

print((max(color)))
for i in G_order:
  print((color[i]))


# Optimized solution
n = int(eval(input()))
G = [[] for _ in range(n)]
edge  = []
for _ in range(n-1):
    a, b = list(map(int, input().split()))
    a -= 1
    b -= 1
    G[a].append(b)
    edge.append(b)

from collections import deque

q = deque()
color = [0]*n
q.append(0)
while q:
    cur = q.popleft()
    c = 1
    for nx in G[cur]:
        if color[cur] == c:
            c += 1
        color[nx] = c
        c += 1
        q.append(nx)

print((max(color)))
for e in edge:
    print((color[e]))
# Original solution
from collections import deque
N = int(eval(input()))
E = [tuple([int(x)-1 for x in input().split()]) for _ in range(N-1)]
K = 0
E_sorted = sorted(E, key=lambda x:x[0])
ans = {}
V = [deque([i for i in range(1, N)]) for _ in range(N)]
for e in E_sorted:
  a, b = e
  c = 1
  req_K = True
  c = V[a].popleft()
  if c > K:
    K = c
  V[b].remove(c)
  ans[e] = c
print(K)
for e in E:
  print((ans[e]))


# Optimized solution
N = int(eval(input()))
E = [tuple([int(x)-1 for x in input().split()]) for _ in range(N-1)]
K = 0
E_sorted = sorted(E, key=lambda x:x[0])
ans = {}
V = [[] for _ in range(N)]
for e in E_sorted:
  a, b = e
  c = 1
  req_K = True
  c = 1
  i = 1
  while i <= K:
    if not (i in V[a]):
      c = i
      req_K = False
      break
    i += 1
  if req_K:
    K += 1
    c = K
  V[a].append(c)
  V[b].append(c)
  ans[e] = c
print(K)
for e in E:
  print((ans[e]))
# Original solution
N = int(eval(input()))
from collections import defaultdict

G = defaultdict(list)
EdaNum = defaultdict(int)

for i in range(N-1):
    a,b = list(map(int,input().split()))
    G[a].append(b)
    G[b].append(a)
    EdaNum[(a,b)] = i
    
ans = [-1]*(N-1)

que = [[1,-1,-1]]
K = 0
visited = [False]*(N+1)

for i in range(1,N+1):
    K = max(K,len(G[i]))

while que != []:
    #print(que)
    now,parent,parentcolor = que.pop()
    visited[now]=True
    used = [False]*(K+1)
    nowcolor = 1
    for i in G[now]:
        #print(i,parent)
        if i != parent:
            if nowcolor == parentcolor:
                nowcolor += 1
            ans[EdaNum[(min(now,i),max(now,i))]] = nowcolor
            nowcolor += 1
            if len(G[i])!=1:
                que.append([i,now, nowcolor-1])
    #print(que)

print(K)
for i in ans:
    print(i)

# Optimized solution
N = int(eval(input()))
from collections import defaultdict

G = defaultdict(list)
EdaNum = defaultdict(int)

for i in range(N-1):
    a,b = list(map(int,input().split()))
    G[a].append(b)
    G[b].append(a)
    EdaNum[(a,b)] = i
    
ans = [-1]*(N-1)

que = [[1,-1,-1]]
K = 0
visited = [False]*(N+1)

for i in range(1,N+1):
    K = max(K,len(G[i]))

while que != []:
    #print(que)
    now,parent,parentcolor = que.pop()
    visited[now]=True
    nowcolor = 1
    for i in G[now]:
        #print(i,parent)
        if i != parent:
            if nowcolor == parentcolor:
                nowcolor += 1
            ans[EdaNum[(min(now,i),max(now,i))]] = nowcolor
            nowcolor += 1
            if len(G[i])!=1:
                que.append([i,now, nowcolor-1])
    #print(que)

print(K)
for i in ans:
    print(i)
# Original solution
from queue import deque

n = int(eval(input()))
l = [list(map(int,input().split())) for _ in range(n-1)]
li = [[0 for i in range(n)]for j in range(n)]

for i,j in l:
    i,j = i-1,j-1
    li[i][j] = 1
    li[j][i] = 1

ans = [[0 for i in range(n)]for j in range(n)]
before_color = {}
before_color[0] = 0
visited_node = [False]*n
visited_node[0] = True

max_color = 1

# 幅優先探索（BFS）
def breadth_first_search(start, W):
    global max_color
    # リストをキューにする
    work_queue = deque([])
    visited = set()
    # 初期化
    work_queue.append(start)
    visited.add(start)

    while work_queue:
        # 今いる頂点
        here = work_queue.popleft()
        # 今いる頂点に隣接する頂点すべてを処理する
        for i, node in enumerate(W[here]):
            # 隣接しなければ何もしない
            if node == 0: continue
            if i not in visited:
                work_queue.append(i)
                visited.add(i)
        color = 1
        for j in work_queue:
            if visited_node[j]:
                continue
            else:
                visited_node[j] = True
            if color == before_color[here]:
                color += 1
            before_color[j] = color
            ans[here][j] = color
            ans[j][here] = color
            max_color = max(max_color,color)
            color += 1
    return visited

breadth_first_search(0,li)
print(max_color)
for i,j in l:
    i,j = i-1,j-1
    print((ans[i][j]))

# Optimized solution
from queue import deque

n = int(eval(input()))
l = [list(map(int,input().split())) for _ in range(n-1)]
li = [[] for _ in range(n)]

for i,j in l:
    i,j = i-1,j-1
    li[i].append(j)
    li[j].append(i)

stack = 0
color = [0]*n

work_queue = deque([])
visited = [False]*n
visited[0] = True
color_list = [0]*n
work_queue.append(stack)
path = {}
ma = 0
while work_queue:
    here = work_queue.popleft()
    color = 1
    for i in li[here]:
        if visited[i]:
            continue
        work_queue.append(i)
        visited[i] = True
        if color_list[here] == color:
            color += 1
        path[(here,i)] = color
        color_list[i] = color
        ma = max(ma,color)
        color += 1

print(ma)
for i,j in l:
    i,j = i-1,j-1
    print((path[(i,j)]))