CodeEff/ECCO huggingface dataset:
# Original solution
import sys

# import re
# import math
# import collections
# import decimal
# import bisect
# import itertools
# import fractions
# import functools
# import copy
# import heapq
# import decimal
# import statistics
import queue

sys.setrecursionlimit(10000001)
INF = 10 ** 16
MOD = 10 ** 9 + 7

ni = lambda: int(sys.stdin.readline())
ns = lambda: list(map(int, sys.stdin.readline().split()))
na = lambda: list(map(int, sys.stdin.readline().split()))


# ===CODE===


def main():
    n = ni()
    edge = [[] for i in range(n)]
    origin_edge = []
    edge_dic = {}
    for i in range(n - 1):
        a, b = ns()
        a -= 1
        b -= 1
        edge[a].append(b)
        edge[b].append(a)
        edge_dic[(a, b)] = -1
        origin_edge.append((a, b))

    max_root = 0
    for e in edge:
        max_root = max(max_root, len(e))

    node_unused_color = [{i for i in range(max_root)} for j in range(n)]

    que = queue.Queue()
    que.put(0)

    while que.qsize() > 0:
        node = que.get()
        for k in edge[node]:
            ai = min(node, k)
            bi = max(node, k)

            if edge_dic[(ai, bi)] > -1:
                continue

            chosen_color = -1
            for tmp_a in node_unused_color[ai]:
                if tmp_a in node_unused_color[bi]:
                    chosen_color = tmp_a
                    break
            node_unused_color[ai] -= {chosen_color}
            node_unused_color[bi] -= {chosen_color}
            edge_dic[(ai, bi)] = chosen_color
            que.put(k)

    print(max_root)
    for a, b in origin_edge:
        print((edge_dic[(a, b)] + 1))


if __name__ == '__main__':
    main()


# Optimized solution
import sys

# import re
# import math
# import collections
# import decimal
# import bisect
# import itertools
# import fractions
# import functools
# import copy
# import heapq
# import decimal
# import statistics
import queue

sys.setrecursionlimit(10000001)
INF = 10 ** 16
MOD = 10 ** 9 + 7

ni = lambda: int(sys.stdin.readline())
ns = lambda: list(map(int, sys.stdin.readline().split()))
na = lambda: list(map(int, sys.stdin.readline().split()))


# ===CODE===


def main():
    n = ni()
    edge = [[] for i in range(n)]
    origin_edge = []
    edge_dic = {}
    for i in range(n - 1):
        a, b = ns()
        a -= 1
        b -= 1
        edge[a].append(b)
        edge[b].append(a)
        edge_dic[(a, b)] = -1
        origin_edge.append((a, b))

    max_root = 0
    for e in edge:
        max_root = max(max_root, len(e))

    que = queue.Queue()
    que.put((0, -1))

    while que.qsize() > 0:
        node, used_color = que.get()
        current_color = 0 if used_color != 0 else 1
        for k in edge[node]:
            ai = min(node, k)
            bi = max(node, k)

            if edge_dic[(ai, bi)] > -1:
                continue

            edge_dic[(ai, bi)] = current_color
            que.put((k, current_color))
            current_color = current_color + 1 if used_color != current_color + 1 else current_color + 2

    print(max_root)
    for a, b in origin_edge:
        print((edge_dic[(a, b)] + 1))


if __name__ == '__main__':
    main()
# Original solution
import sys
sys.setrecursionlimit(100000)


def rootedTree(node,parent,root,add):
    A.append([node,parent,root,add])
    for root_num,num in root:
        if len(tree[root_num])!=0:
            rootedTree(root_num,node,tree[root_num],num)
        else:
            A.append([root_num,node,tree[root_num],num])


n=int(eval(input()))
AB=[list(map(int,input().split()))+[i+1] for i in range(n-1)]
A=[]
tree=[[] for i in range(n+1)]
for a,b,c in AB:
    tree[a] +=[[b,c]]

rootedTree(1,0,tree[1],0)
ans=[0]*n
for node,parent,root,num in A:
    flag=0
    for i,j in enumerate(root):
        if ans[num]==i+1:flag=1
        if flag:
            ans[j[1]]=i+2
            continue
        ans[j[1]]=i+1

print((max(ans)))
for i in range(1,n):print((ans[i]))

# Optimized solution
import sys
sys.setrecursionlimit(100000)


def rootedTree(node,parent,root,add):
    A.append([node,parent,root,add])
    for root_num,num in root:
            rootedTree(root_num,node,tree[root_num],num)


n=int(eval(input()))
AB=[list(map(int,input().split()))+[i+1] for i in range(n-1)]
A=[]
tree=[[] for i in range(n+1)]
for a,b,c in AB:
    tree[a] +=[[b,c]]

rootedTree(1,0,tree[1],0)
ans=[0]*n
for node,parent,root,num in A:
    flag=0
    for i,j in enumerate(root):
        if ans[num]==i+1:flag=1
        if flag:
            ans[j[1]]=i+2
            continue
        ans[j[1]]=i+1

print((max(ans)))
for i in range(1,n):print((ans[i]))
# Original solution
import sys
sys.setrecursionlimit(100000)


def rootedTree(node,parent,root,num):
    A.append([node,parent,root,num])
    for root_num,num in root:
            rootedTree(root_num,node,tree[root_num],num)


n=int(eval(input()))
AB=[list(map(int,input().split()))+[i+1] for i in range(n-1)]
A=[]
tree=[[] for i in range(n+1)]
for a,b,c in AB:
    tree[a] +=[[b,c]]

rootedTree(1,0,tree[1],0)
ans=[0]*n
for node,parent,root,num in A:
    flag=0
    for i,j in enumerate(root):
        if ans[num]==i+1:flag=1
        ans[j[1]]=i+1+flag

print((max(ans)))
for i in range(1,n):print((ans[i]))

# Optimized solution
import sys
sys.setrecursionlimit(10**7)


def rootedTree(node,parent,root,num):
    A.append([node,parent,root,num])
    for root_num,num in root:
            rootedTree(root_num,node,tree[root_num],num)


n=int(eval(input()))
AB=[list(map(int,input().split()))+[i+1] for i in range(n-1)]
A=[]
tree=[[] for i in range(n+1)]
for a,b,c in AB:
    tree[a] +=[[b,c]]

rootedTree(1,0,tree[1],0)
ans=[0]*n
for node,parent,root,num in A:
    flag=0
    for i,j in enumerate(root):
        if ans[num]==i+1:flag=1
        ans[j[1]]=i+1+flag

print((max(ans)))
for i in range(1,n):print((ans[i]))
# Original solution
from collections import deque
import sys
input = sys.stdin.readline

n = int(eval(input()))

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


ans = [[0 for _ in range(n)] for __ in range(n)]
visited = [False]*n

q = deque([(0,0)])
visited[0] = True

mx = 0
while q:
    key,v = q.popleft()
    i = 1
    for x in edges[v]:
        if not visited[x]:
            if key != i:
                visited[x] = True
                ans[v][x] = i
                ans[x][v] = i
                q.append((i,x))
                mx = max(mx,i)
                i += 1
            else:
                visited[x] = True
                i += 1
                ans[v][x] = i
                ans[x][v] = i
                q.append((i,x))
                mx = max(mx,i)
                i += 1

print(mx)
for i in range(n-1):
    print((ans[l[i][0]][l[i][1]]))



# Optimized solution
from collections import deque
import sys
input = sys.stdin.readline

n = int(eval(input()))

edges = [[] for _ in range(n)]
l = {}
for i in range(n-1):
    a,b = list(map(int,input().split()))
    edges[a-1].append(b-1)
    edges[b-1].append(a-1)
    l[(a-1,b-1)]=i
    l[(b-1,a-1)]=i


ans = [0]*(n-1)
visited = [False]*n

q = deque([(0,0)])
visited[0] = True

mx = 0
while q:
    key,v = q.popleft()
    i = 1
    for x in edges[v]:
        if not visited[x]:
            if key != i:
                visited[x] = True
                ans[l[(v,x)]]=i
                q.append((i,x))
                mx = max(mx,i)
                i += 1
            else:
                visited[x] = True
                i += 1
                ans[l[(v,x)]]=i
                q.append((i,x))
                mx = max(mx,i)
                i += 1

print(mx)
for i in range(n-1):
    print((ans[i]))
# Original solution
from collections import deque
n = int(eval(input()))
l = [0 for i in range(n)]
l2 = []
l3 = [[] for i in range(n+1)]
for i in range(n-1):
    a,b = list(map(int,input().split()))
    l2.append([a,b])
    l3[a].append(b)
    l3[b].append(a)
    l[a-1] += 1
    l[b-1] += 1
a = max(l)
print(a)
rl = [0 for i in range(n+1)]
d = deque()
d.append([1,0])
rl[1] = 1
cl = [[0 for i in range(n+1)] for i in range(n+1)]
while len(d):
    now,c = d.popleft()
    rl[now] = 1
    if c == 0:
        count = 1
        for i in l3[now]:
            cl[now][i] = count
            d.append([i,count])
            count += 1
    else:
        count = 1
        for i in l3[now]:
            if rl[i] == 0:
                if c == count:
                    count += 1
                cl[now][i] = count
                d.append([i,count])
                count += 1
for i in range(n-1):
    print((cl[l2[i][0]][l2[i][1]]))

# Optimized solution
from collections import deque
n = int(eval(input()))
l = [0 for i in range(n)]
l2 = []
l3 = [[] for i in range(n+1)]
for i in range(n-1):
    a,b = list(map(int,input().split()))
    l2.append([a,b])
    l3[a].append(b)
    l3[b].append(a)
    l[a-1] += 1
    l[b-1] += 1
a = max(l)
print(a)
rl = [0 for i in range(n+1)]
d = deque()
d.append([1,0])
rl[1] = 1
dic = {}
while len(d):
    now,c = d.popleft()
    rl[now] = 1
    if c == 0:
        count = 1
        for i in l3[now]:
            dic["{0},{1}".format(now,i)] = count
            d.append([i,count])
            count += 1
    else:
        count = 1
        for i in l3[now]:
            if rl[i] == 0:
                if c == count:
                    count += 1
                dic["{0},{1}".format(now,i)] = count
                d.append([i,count])
                count += 1
for i in range(n-1):
    print((dic["{0},{1}".format(l2[i][0],l2[i][1])]))
# Original solution
N = int(input())

A = set([i for i in range(1, 10**5)])
s = [[] for _ in range(N)]
r = []
for _ in range(N-1):
  a, b = map(int, input().split())
  n = min(A - set(s[a-1] + s[b-1]))
  s[a-1] += [n]
  s[b-1] += [n]
  r.append(n)

print(max(r))
print(*r, sep='\n')


# Optimized solution
from collections import deque

N = int(input())

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


q = deque()
q.append([0, 0, 0])

colors = [0] * (N-1)
while q:
  node, parent, edge_color = q.popleft()
  c = 1
  for child, index in G[node]:
    if child == parent:
      continue
    
    if c == edge_color:
      c += 1
    
    q.append([child, node, c])
    colors[index] = c
    c += 1

print(max(colors))
print(*colors, sep='\n')
# Original solution
import sys
sys.setrecursionlimit(10**6)
n = int(eval(input()))
data = [[] for _ in range(n)]
for i in range(n-1):
    a,b = list(map(int,input().split()))
    a -= 1
    b -= 1
    data[a].append([i,b])  # i本目でbに
    data[b].append([i,a])

k = max(len(data[i]) for i in range(n))
print(k)
ans = [-1 for i in range(n)]


stack = [[0,n,k]]
while stack:
    now,pre,pre_path = stack.pop()
    color = [True for i in range(k + 1)]
    color[ans[pre_path]] = False

    for nex_path, nex in data[now]:
        if nex == pre: continue
        for num, c in enumerate(color):
            if c:
                ans[nex_path] = num
                color[num] = False
                stack.append([nex, now, nex_path])
                break


for x  in ans[:-1]:
    print((x+1))

# Optimized solution
n = int(input())
G = [[] for _ in range(n)]
d = {}
for i in range(n-1):
    a,b = map(int,input().split())
    a -= 1
    b -= 1
    G[a].append(b)
    G[b].append(a)
    d[(a,b)] = d[(b,a)] = i

k = 0
ans = [None]*(n-1)

stack = [(0,-1)] #node, par

while stack:
    now,pre = stack.pop()
    color = 1
    for nex in G[now]:
        if nex == pre:continue
        stack.append((nex,now))
        if pre != -1:
            if color == ans[d[(now,pre)]]:
                color += 1
        ans[d[(now,nex)]] = color
        k = max(k,color)
        color += 1

print(k)
print(*ans, sep="\n")
# Original solution
import sys
input = sys.stdin.readline

N = int(eval(input()))
edges = [[int(i) for i in input().split()] for _ in range(N-1)]
edge_col = [0]*(N-1)
cols = [set() for _ in range(N)]
gp = [[] for _ in range(N)]

for ind, (a, b) in enumerate(edges):
    gp[a-1].append((b-1, ind))
    gp[b-1].append((a-1, ind))

seen = set()
stk = [0]
max_col = 0
while stk:
    pt = stk.pop()
    if(pt in seen):
        continue
    seen.add(pt)
    for nxt, ind in gp[pt]:
        if(nxt in seen):
            continue
        col = 1
        while col in cols[pt]:
            col += 1
        max_col = max(col, max_col)
        edge_col[ind] = col
        cols[pt].add(col)
        cols[nxt].add(col)

        stk.append(nxt)

print(max_col)
for i in edge_col:
    print(i)


# Optimized solution
import sys
input = sys.stdin.readline

N = int(eval(input()))
edges = [[int(i) for i in input().split()] for _ in range(N-1)]
edge_col = [0]*(N-1)
gp = [[] for _ in range(N)]

for ind, (a, b) in enumerate(edges):
    gp[a-1].append((b-1, ind))
    gp[b-1].append((a-1, ind))

cols = [set(list([x+1 for x in range(len(gp[i]))])) for i in range(N)]

seen = set()
stk = [0]
max_col = 0
while stk:
    pt = stk.pop()
    #print(pt)
    if(pt in seen):
        continue
    seen.add(pt)
    for nxt, ind in gp[pt]:
        if(nxt in seen):
            continue
        col = cols[pt].pop()
        max_col = max(col, max_col)
        edge_col[ind] = col
        try:
            cols[nxt].remove(col)
        except:
            pass

        stk.append(nxt)

print(max_col)
for i in edge_col:
    print(i)
# Original solution
import sys
sys.setrecursionlimit(10**6)
def dfs(G,v,p,color):
    cnt=1
    for nv in G[v]:
        if(nv==p):
            continue
        if cnt in liset[v]:
            while(cnt in liset[v]):
                cnt+=1
        liset[v].add(cnt)
        liset[nv].add(cnt)
        dic[str(v)+'t'+str(nv)]=cnt
        dfs(G,nv,v,cnt)
N=int(eval(input()))
G=[[] for i in range(N)]
e=[]
for i in range(N-1):
    a,b=[int(x)-1 for x in input().split()]
    G[a].append(b)
    G[b].append(a)
    e.append([a,b])
l=0
for i in range(N):
    l=max(l,len(G[i]))
liset=[set() for i in range(N)]
dic={}
dfs(G,0,-1,0)
print(l)
for i in range(N-1):
    if str(e[i][0])+'t'+str(e[i][1]) in dic:
        print((dic[str(e[i][0])+'t'+str(e[i][1])]))
    else:
        print((dic[str(e[i][1])+'t'+str(e[i][0])]))

# Optimized solution
import sys
sys.setrecursionlimit(10**6)
def dfs(G,v,p,color):
    cnt=1
    for nv in G[v]:
        if(nv==p):
            continue
        while(cnt in s[v]):
                cnt+=1
        s[v].add(cnt)
        s[nv].add(cnt)
        dic[tuple(sorted([v,nv]))]=cnt
        dfs(G,nv,v,cnt)
        
N=int(eval(input()))
G=[[] for i in range(N)]
e=[]
s=[set() for i in range(N)]
dic={}
for i in range(N-1):
    a,b=[int(x)-1 for x in input().split()]
    G[a].append(b)
    G[b].append(a)
    e.append(sorted([a,b]))
l=0
for i in range(N):
    l=max(l,len(G[i]))
dfs(G,0,-1,0)
print(l)
for i in range(N-1):
    print((dic[e[i][0],e[i][1]]))
# Original solution
# ある頂点で、子供に対して順に1,2,3...と辺の色を渡していく
# 親から来た色を持っておき、親から来た色と同色になったときはスキップして次の色を渡す
# グラフ構築の際に、辺の番号を持っておく

import sys
readline = sys.stdin.readline

N = int(readline())
G = [[] for i in range(N)]
for i in range(N - 1):
  a,b = list(map(int,readline().split()))
  G[a-1].append([b-1,i])
  G[b-1].append([a-1,i])
  
ans = [0 for i in range(N - 1)]
from collections import deque
# 頂点、親から来た色、親
q = deque([[0, 0, -1]])
while q:
  v,pcol,parent = q.popleft()
  cnt = 1
  for child in G[v]:
    if child[0] == parent:
      continue
    if cnt == pcol:
      cnt += 1
    ans[child[1]] = cnt
    q.append([child[0],cnt,v])
    cnt += 1

print((max(ans)))
for a in ans:
  print(a)

# Optimized solution
import sys
readline = sys.stdin.readline

N = int(readline())

G = [[] for i in range(N)]
from collections import defaultdict
E = defaultdict(int)

for i in range(N - 1):
  a,b = list(map(int,readline().split()))
  G[a - 1].append(b - 1)
  G[b - 1].append(a - 1)
  E[(a - 1, b - 1)] = i

from collections import deque
q = deque([])
ans = [None] * (N - 1)

q.append([0, -1, 0])
maxcol = 0
while q:
  v, parent, color = q.popleft()
  if color > maxcol:
    maxcol = color
  if (v, parent) in E:
    ans[E[(v, parent)]] = color
  elif (parent, v) in E:
    ans[E[(parent, v)]] = color
  next_col = 0
  for child in G[v]:
    if child == parent:
      continue
    next_col += 1
    if next_col == color:
      next_col += 1
    q.append([child, v, next_col])
    
print(maxcol)
for a in ans:
  print(a)
# Original solution
import sys
from collections import deque
read = sys.stdin.read

N, *ab = list(map(int, read().split()))
graph = [[] for _ in range(N + 1)]

for a, b in zip(*[iter(ab)] * 2):
    graph[a].append(b)

color = [0] * (N + 1)
queue = deque([1])
color_v = [[] for _ in range(N + 1)]

while queue:
    V = queue.popleft()
    number = 1
    for v in graph[V]:
        if number in color_v[V]:
            number += 1
        color[v] = number
        color_v[V].append(number)
        color_v[v].append(number)
        queue.append(v)
        number += 1

print((max(color)))
for a, b in zip(*[iter(ab)] * 2):
    print((color[b]))

# Optimized solution
import sys
from collections import deque
read = sys.stdin.read

N, *ab = list(map(int, read().split()))
graph = [[] for _ in range(N + 1)]

for a, b in zip(*[iter(ab)] * 2):
    graph[a].append(b)

color = [0] * (N + 1)
queue = deque([1])
color_v = [set() for _ in range(N + 1)]

while queue:
    V = queue.popleft()
    number = 1
    for v in graph[V]:
        if number in color_v[V]:
            number += 1
        color[v] = number
        color_v[V].add(number)
        color_v[v].add(number)
        queue.append(v)
        number += 1

print((max(color)))
for a, b in zip(*[iter(ab)] * 2):
    print((color[b]))
# Original solution
import sys
from collections import deque
read = sys.stdin.read

N, *ab = list(map(int, read().split()))
graph = [[] for _ in range(N + 1)]

for a, b in zip(*[iter(ab)] * 2):
    graph[a].append(b)

color = [0] * (N + 1)
queue = deque([1])
color_v = [set() for _ in range(N + 1)]

while queue:
    V = queue.popleft()
    number = 1
    for v in graph[V]:
        if number in color_v[V]:
            number += 1
        color[v] = number
        color_v[V].add(number)
        color_v[v].add(number)
        queue.append(v)
        number += 1

print((max(color)))
for a, b in zip(*[iter(ab)] * 2):
    print((color[b]))

# Optimized solution
import sys
from collections import deque
read = sys.stdin.read

N, *ab = list(map(int, read().split()))
graph = [[] for _ in range(N + 1)]

for a, b in zip(*[iter(ab)] * 2):
    graph[a].append(b)

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

while queue:
    V = queue.popleft()
    number = 1
    for v in graph[V]:
        if number == color[V]:
            number += 1
        color[v] = number
        queue.append(v)
        number += 1

print((max(color)))
for a, b in zip(*[iter(ab)] * 2):
    print((color[b]))
# Original solution
N=int(eval(input()))
G=[[] for i in range(N)]
a=[]
b=[]

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

k=[0]*N

from collections import deque

q=deque([0])
C=[[-1]*N for i in range(N)]
p=[-1]*N

kmx=0
while q:
    x=q.popleft()
    for i in G[x]:
        if C[x][i]!=-1:continue
        if p[x]==k[x]:
            k[x]+=1

        C[x][i] = k[x]
        C[i][x] = k[x]
        p[i] = k[x]
        k[x] += 1
        kmx=max(kmx,k[x])
        q.append(i)

print(kmx)
for i in range(N-1):
    print((C[a[i]][b[i]]+1))




# Optimized solution
N=int(eval(input()))
G=[[] for i in range(N)]
a=[]
b=[]

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

k=[0]*N

from collections import deque

q=deque([0])
visited=[0]*N
ans={}
p=[-1]*N

kmx=0
while q:
    x=q.popleft()
    visited[x]=1
    cnt=1
    for i in G[x]:
        if visited[i]!=0:continue
        if p[x]==cnt:
            cnt+=1
        ans[(x,i)]=cnt
        ans[(i,x)]=cnt

        p[i] = cnt
        cnt += 1
        kmx=max(kmx,cnt-1)
        q.append(i)

print(kmx)
for i in range(N-1):
    print((ans[(a[i],b[i])]))
# Original solution
import sys
input = sys.stdin.readline
N = int(eval(input()))
X = [[] for _ in range(N)]
P = [-1] * N
for i in range(N-1):
    a, b = list(map(int, input().split()))
    X[a-1].append((i, b-1))
    #print(X)
    P[b-1] = a-1

Q = [(0, -1)]
ANS = [-1] * (N-1)
while Q:
    x, c0 = Q.pop()
    c = 1
    for i, y in X[x]:
        if c == c0: c += 1
        ANS[i] = c
        Q.append((y, c))
        c += 1

print((max(ANS)))
for ans in ANS:
    print(ans)

# Optimized solution
import sys
input = sys.stdin.readline
N = int(eval(input()))
X = [[] for _ in range(N)]
P = [-1] * N
for i in range(N-1):
    a, b = list(map(int, input().split()))
    X[a-1].append((i, b-1))
    #print(X)
    #P[b-1] = a-1
#print(X)

Q = [(0, -1)]
ANS = [-1] * (N-1)
maxc = 0
while Q:
    x, c0 = Q.pop()
    c = 1
    for i, y in X[x]:
        if c == c0: c += 1
        ANS[i] = c
        if c>maxc:maxc=c
        Q.append((y, c))
        c += 1

print(maxc)
for ans in ANS:
    print(ans)
# Original solution
import sys
input = sys.stdin.readline
N = int(eval(input()))
X = [[] for _ in range(N)]
P = [-1] * N
for i in range(N-1):
    a, b = list(map(int, input().split()))
    X[a-1].append((i, b-1))
    #print(X)
    #P[b-1] = a-1
#print(X)

Q = [(0, -1)]
ANS = [-1] * (N-1)
maxc = 0
while Q:
    x, c0 = Q.pop()
    c = 1
    for i, y in X[x]:
        if c == c0: c += 1
        ANS[i] = c
        if c>maxc:maxc=c
        Q.append((y, c))
        c += 1

print(maxc)
for ans in ANS:
    print(ans)

# Optimized solution
import sys
input = sys.stdin.readline
N = int(eval(input()))
X = [[] for _ in range(N)]
P = [-1] * N
for i in range(N-1):
    a, b = list(map(int, input().split()))
    X[a-1].append((i, b-1))
    #print(X)
    #P[b-1] = a-1
#print(X)

Q = [(0, -1)]
ANS = [-1] * (N-1)
cmax = 0
while Q:
    x, c0 = Q.pop()
    c = 1
    for i, y in X[x]:
        if c == c0: c += 1
        ANS[i] = c
        Q.append((y, c))
        c += 1
    cmax = max(cmax, c-1)

print(cmax)
for ans in ANS:
    print(ans)
# Original solution
import sys
from collections import deque
input = sys.stdin.readline
N = int(eval(input()))
X = [deque() for _ in range(N)]
P = [-1] * N
for i in range(N-1):
    a, b = list(map(int, input().split()))
    X[a-1].append((i, b-1))
    #print(X)
    #P[b-1] = a-1
#print(X)

Q = deque([(0, -1)])
ANS = [-1] * (N-1)
cmax = 0
while Q:
    x, c0 = Q.pop()
    c = 1
    for i, y in X[x]:
        if c == c0: c += 1
        ANS[i] = c
        Q.appendleft((y, c))
        c += 1
    cmax = max(cmax, c-1)

print(cmax)
for ans in ANS:
    print(ans)

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

Q = deque([(0, -1)])
ANS = [-1] * (N-1)
cmax = 0
while Q:
    x, c0 = Q.pop()
    c = 1
    for i, y in X[x]:
        if c == c0: c += 1
        ANS[i] = c
        Q.appendleft((y, c))
        c += 1
    cmax = max(cmax, c-1)

print(cmax)
for ans in ANS:
    print(ans)