CodeEff/ECCO huggingface dataset:
# Original solution
"""
challenge case

in:
3
1 3
2 3

out:
1
1
1
"""

from collections import deque

def main():
	N, *AB = list(map(int, open(0).read().split()))
	B = AB[1::2]

	E = [[] for _ in range(N + 1)]
	for a, b in zip(*[iter(AB)] * 2):
		E[a] += b,

	Q = deque([1])
	C = [0] * (N + 1)
	while Q:
		v = Q.popleft()
		c = 0
		for u in E[v]:
			c += 1 + (c + 1 == C[v])
			C[u] = c
			Q += u,

	print((max(C)))
	for b in B:
		print((C[b]))

main()

# Optimized solution
"""
challenge case

in:
3
1 3
2 3

out:
1
1
1
"""

from collections import deque

def main():
	N, *AB = list(map(int, open(0).read().split()))
	B = AB[1::2]

	E = [[] for _ in range(N + 1)]
	for a, b in zip(*[iter(AB)] * 2):
		E[a].append(b)

	Q = deque([1])
	C = [0] * (N + 1)
	while Q:
		v = Q.popleft()
		c = 0
		for u in E[v]:
			c += 1 + (c + 1 == C[v])
			C[u] = c
			Q.append(u)

	print((max(C)))
	for b in B:
		print((C[b]))

main()
# Original solution
from collections import defaultdict, deque, Counter

N = int(eval(input()))

edges = {}
counter = Counter()
nodes = defaultdict(set)

K = 0
for i in range(N - 1):
    u, v = list(map(int, input().split(' ')))
    counter[u] += 1
    counter[v] += 1
    K = max(K, counter[u], counter[v])
    nodes[u].add(v)
    nodes[v].add(u)
    edges[(u, v)] = i

colors = set([1 + k for k in range(K)])
checked = set()
queue = deque([(1, 0)])
edge_colors = [0] * N

while queue:
    u, uc = queue.popleft()
    checked.add(u)
    if len(checked) == N:
        break
    for v, vc in zip(nodes[u] - checked, colors - {uc}):
        edge_colors[edges[(min(u, v), max(u, v))]] = vc
        queue.append((v, vc))

print(K)
for i in range(N - 1):
    print((edge_colors[i]))


# Optimized solution
from collections import defaultdict, deque, Counter

N = int(eval(input()))

counter = Counter()
nodes = defaultdict(list)
edges = []

for i in range(N - 1):
    u, v = list(map(int, input().split(' ')))
    nodes[u].append((v, i))
    nodes[v].append((u, i))
    edges.append((u, v))

K = 0
for node in list(nodes.values()):
    K = max(K, len(node))

checked = set()
queue = deque([(1, 0)])
edge_colors = [0] * N

while queue:
    u, uc = queue.popleft()
    checked.add(u)
    color = 1
    for v, e in nodes[u]:
        if v in checked:
            continue
        if color == uc:
            color += 1
        edge_colors[e] = color
        queue.append((v, color))
        color += 1

print(K)
for i in range(N - 1):
    print((edge_colors[i]))
# Original solution
import sys
from collections import deque
input = sys.stdin.readline
N = int(eval(input()))
G = [[] for _ in range(N)]
ans = {}
queue = deque([])
e = []
for l in range(N-1):
    temp = list(map(int,input().split()))
    temp[0] -= 1
    temp[1] -= 1
    e.append(tuple(temp))
    ans[(temp[0],temp[1])] = 0
    ans[(temp[1],temp[0])] = 0
    G[temp[0]].append(temp[1])
    G[temp[1]].append(temp[0])
    if l == 0:
        queue.append(temp[0])
#使えない色
nuc = [[0] for _ in range(N)]
#使った色
auc = []
#答え
def bfs(x):
    k = 1
    for i in G[x]:
        if ans[(x,i)] ==0:
            queue.append(i)
            flag = 1
            while flag:
                if k not in nuc[x]:         
                    ans[(x,i)] = k
                    ans[(i,x)] = k
                    nuc[x].append(k)
                    nuc[i].append(k)
                    if k not in auc:
                        auc.append(k)
                    flag = 0
                else:
                    k += 1
                
while len(queue) > 0:
    next_ = queue.popleft()
    bfs(next_)
print((len(auc)))
for m in e:
    print((ans[m]))


# Optimized solution
def main():
    import sys
    from collections import deque
    input = sys.stdin.readline
    N = int(eval(input()))
    G = [[] for _ in range(N)]
    ans = {}
    queue = deque([])
    e = []
    for l in range(N-1):
        temp = list(map(int,input().split()))
        temp[0] -= 1
        temp[1] -= 1
        e.append(tuple(temp))
        ans[(temp[0],temp[1])] = 0
        ans[(temp[1],temp[0])] = 0
        G[temp[0]].append(temp[1])
        G[temp[1]].append(temp[0])
        if l == 0:
            queue.append(temp[0])
    #使えない色
    nuc = [[0] for _ in range(N)]
    #使った色
    auc = []
    #答え
    def bfs(x):
        k = 1
        for i in G[x]:
            if ans[(x,i)] ==0:
                queue.append(i)
                flag = 1
                while flag:
                    if k not in nuc[x]:         
                        ans[(x,i)] = k
                        ans[(i,x)] = k
                        nuc[x].append(k)
                        nuc[i].append(k)
                        if k not in auc:
                            auc.append(k)
                        flag = 0
                    else:
                        k += 1
                    
    while len(queue) > 0:
        next_ = queue.popleft()
        bfs(next_)
    print((len(auc)))
    for m in e:
        print((ans[m]))
if __name__ == '__main__':
    main()
# Original solution
import sys
def input():
    return sys.stdin.readline()[:-1]
import math
from itertools import permutations, combinations
from collections import deque

sys.setrecursionlimit(10**7)
N = int(eval(input()))
ab = []

edges = [[] for _ in range(N)]
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)
    ab.append((a, b))

K = max(list(map(len, edges)))
print(K)

adjm = [[0]*N for _ in range(N)]

Q = deque()
for edge in edges[0]:
    Q.append((0, edge))

while Q:
    labels = set(i for i in range(1, K+1))
    points = Q.popleft()
    p0, p1 = points

    set1 = set(adjm[p0])
    can_use_labels = labels - (set1)
    use_label = can_use_labels.pop()


    adjm[p0][p1] = use_label
    adjm[p1][p0] = use_label

    for p in edges[p1]:
        if adjm[p1][p] == 0:
            Q.append((p1, p))

for abi in ab:
    a, b = abi[0], abi[1]
    print((adjm[a-1][b-1]))

# Optimized solution
import sys
def input():
    return sys.stdin.readline()[:-1]
import math
from itertools import permutations, combinations
from collections import deque

sys.setrecursionlimit(10**7)
N = int(eval(input()))
ab = [list(map(int, input().split())) for _ in range(N-1)]

edges = [[] for _ in range(N)]
for abi in ab:
    a, b = abi[0], abi[1]
    edges[a-1].append(b-1)
    edges[b-1].append(a-1)

K = max(list(map(len, edges)))
print(K)

adjm = [[0]*N for _ in range(N)]

Q = deque()
for edge in edges[0]:
    Q.append((0, edge))

while Q:
    labels = set(i for i in range(1, K+1))
    points = Q.popleft()
    p0, p1 = points

    set1 = set(adjm[p0])
    can_use_labels = labels - set1
    use_label = can_use_labels.pop()

    adjm[p0][p1] = use_label
    adjm[p1][p0] = use_label

    for p in edges[p1]:
        if p != p0:
            Q.append((p1, p))

for abi in ab:
    a, b = abi[0], abi[1]
    print((adjm[a-1][b-1]))
# Original solution
from collections import deque
def color_available(unavailable, K):
    idx = 0
    L = len(unavailable)
    unavailable = sorted(unavailable)
    for color in range(K):
        if idx < L and color == unavailable[idx]:
            idx += 1
        else:
            yield color

def bfs(graph, N, K, start):
    colors = [dict() for _ in range(N)]
    visited = [0] * N
    visited[start] = 1
    que = deque([start])
    while que:
        node = que.popleft()
        gen = color_available(list(colors[node].values()), K)
        color = 1
        for n in graph[node]:
            if not visited[n]:
                visited[n] = 1
                color = next(gen)
                colors[node][n] = color
                colors[n][node] = color
                que.append(n)
    return colors

N = int(eval(input()))
graph = [[] for _ in range(N)]
inputs = tuple(tuple([int(n) - 1 for n in input().split()]) for _ in range(N - 1))
counts = [0] * N
for i, j in inputs:
    graph[i].append(j)
    graph[j].append(i)
    counts[i] += 1
    counts[j] += 1
K = max(counts)
colors = bfs(graph, N, K, 0)
print(K)
for i, j in inputs:
    print((colors[i][j] + 1))

# Optimized solution
from collections import deque
def color_available(unavailable, K):
    idx = 0
    L = len(unavailable)
    unavailable = sorted(unavailable)
    for color in range(K):
        if idx < L and color == unavailable[idx]:
            idx += 1
        else:
            yield color

def bfs(graph, N, K, start):
    colors = [dict() for _ in range(N)]
    visited = [0] * N
    visited[start] = 1
    que = deque([start])
    while que:
        node = que.popleft()
        gen = color_available(list(colors[node].values()), K)
        for n in graph[node]:
            if not visited[n]:
                visited[n] = 1
                colors[node][n] = colors[n][node] = next(gen)
                que.append(n)
    return colors

N = int(eval(input()))
graph = [[] for _ in range(N)]
inputs = tuple(tuple([int(n) - 1 for n in input().split()]) for _ in range(N - 1))
counts = [0] * N
for i, j in inputs:
    graph[i].append(j)
    graph[j].append(i)
    counts[i] += 1
    counts[j] += 1
K = max(counts)
colors = bfs(graph, N, K, 0)
print(K)
for i, j in inputs:
    print((colors[i][j] + 1))
# Original solution
from collections import deque
def main():
    N = int(eval(input()))
    # 辺の集合を隣接リストとして入力
    E = [[] for i 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から幅優先探索
    queue = deque([1])
    color = [0] * (N+1) 
    while queue:
        V = queue.popleft()
        c = 1
        for i in E[V]:
            if c == color[V]:
                c += 1
            color[i] = c
            c += 1
            queue.append(i)

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


if __name__ == "__main__":
    main()


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

def main():
    N, *ab = list(map(int, read().split()))
    E = [[] for _ in range(N + 1)]
    edge_order = []
    
    for a, b in zip(*[iter(ab)] * 2):
        E[a].append(b)
        edge_order.append(b)
    
    # 頂点1から幅優先探索
    queue = deque([1])
    color = [0] * (N+1) 
    while queue:
        V = queue.popleft()
        c = 1
        for i in E[V]:
            if c == color[V]:
                c += 1
            color[i] = c
            c += 1
            queue.append(i)

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


if __name__ == "__main__":
    main()
# Original solution
from collections import deque
N = int(eval(input()))
G = {i:[] for i in range(1,N+1)}
E = {}
A = []
for _ in range(N-1):
    a,b = list(map(int,input().split()))
    A.append((a,b))
    G[a].append(b)
    G[b].append(a)
    E[(a,b)] = 0
hist = [0 for _ in range(N+1)]
heap = deque([1])
c = 1
for y in G[1]:
    E[(1,y)]=c
    c += 1
K = c-1
hist[1]=1
while heap:
    x = heap.popleft()
    for y in G[x]:
        if hist[y]==0:
            K = max(K,len(G[y]))
            col = [0 for _ in range(K+1)]
            for z in G[y]:
                if y<z:
                    col[E[(y,z)]]=1
                else:
                    col[E[(z,y)]]=1
            cur = 1
            for z in G[y]:
                if y<z and E[(y,z)]==0:
                    for i in range(cur,K+1):
                        if col[i]==0:
                            E[(y,z)]=i
                            col[i]=1
                            cur = i+1
                            break
                elif z<y and E[(z,y)]==0:
                    for i in range(cur,K+1):
                        if col[i]==0:
                            E[(z,y)]=i
                            col[i]=1
                            cur = i+1
                            break
            heap.append(y)
            hist[y]=1
print(K)
for e in A:
    print((E[e]))

# Optimized solution
from collections import deque
N = int(eval(input()))
G = {i:[] for i in range(1,N+1)}
E = {}
A = []
for _ in range(N-1):
    a,b = list(map(int,input().split()))
    A.append((a,b))
    G[a].append(b)
    G[b].append(a)
    E[(a,b)] = 0
hist = [0 for _ in range(N+1)]
heap = deque([1])
c = 1
for y in G[1]:
    E[(1,y)]=c
    c += 1
K = c-1
hist[1]=1
while heap:
    x = heap.popleft()
    for y in G[x]:
        if hist[y]==0:
            K = max(K,len(G[y]))
            col = [0 for _ in range(min(K,len(G[y]))+1)]
            for z in G[y]:
                if y<z and E[(y,z)]<len(col):
                    col[E[(y,z)]]=1
                elif z<y and E[(z,y)]<len(col):
                    col[E[(z,y)]]=1
            cur = 1
            for z in G[y]:
                if y<z and E[(y,z)]==0:
                    for i in range(cur,K+1):
                        if col[i]==0:
                            E[(y,z)]=i
                            cur = i+1
                            break
                elif z<y and E[(z,y)]==0:
                    for i in range(cur,K+1):
                        if col[i]==0:
                            E[(z,y)]=i
                            cur = i+1
                            break
            heap.append(y)
            hist[y]=1
print(K)
for e in A:
    print((E[e]))
# Original solution
from collections import Counter,defaultdict,deque
from heapq import heappop,heappush,heapify
import sys,bisect,math,itertools,fractions,pprint
sys.setrecursionlimit(10**8)
mod = 10**9+7
mod2 = 998244353
INF = float('inf')
def inp(): return int(sys.stdin.readline())
def inpl(): return list(map(int, sys.stdin.readline().split()))
def inpln(n): return list(int(sys.stdin.readline()) for i in range(n))

n = inp()
aa = [0] * (n-1)
bb = [0] * (n-1)
g = [[] for i in range(n)]
res = defaultdict(lambda : defaultdict(int))
for i in range(n-1):
    a,b = inpl()
    aa[i] = a-1
    bb[i] = b-1
    g[a-1].append(b-1)
    g[b-1].append(a-1)
def dfs(i,c=-1,p=-1):
    # print('i:{}'.format(i))
    cnt = 1
    for j in g[i]:
        # print(res[j][i])
        if j == p:
            continue
        if cnt == c:
            cnt += 1
        res[i][j] = cnt
        res[j][i] = cnt
        cnt += 1
        dfs(j,res[i][j],i)
dfs(0)
m = 0
for i in g:
    m = max(m, len(i))
print(m)
for i in range(n-1):
    print((res[aa[i]][bb[i]]))

# Optimized solution
from collections import Counter,defaultdict,deque
from heapq import heappop,heappush,heapify
import sys,bisect,math,itertools,fractions,pprint
sys.setrecursionlimit(10**8)
mod = 10**9+7
mod2 = 998244353
INF = float('inf')
def inp(): return int(sys.stdin.readline())
def inpl(): return list(map(int, sys.stdin.readline().split()))
def inpln(n): return list(int(sys.stdin.readline()) for i in range(n))

n = inp()
g = [[] for i in range(n)]
edges = []
res = [defaultdict(int) for i in range(n)]
for i in range(n-1):
    a,b = inpl()
    a -= 1
    b -= 1
    g[a].append(b)
    g[b].append(a)
    edges.append([a,b])
def dfs(e,prev_edge=-1,prev_color=-1):
    cnt = 1
    for ne in g[e]:
        if res[e][ne] or ne == prev_edge:
            continue
        if cnt == prev_color:
            cnt += 1
        res[e][ne] = cnt
        res[ne][e] = cnt
        dfs(ne,e,cnt)
        cnt += 1
dfs(0)
m = 0
for eee in g:
    m = max(m, len(eee))
print(m)
for a,b in edges:
    print((res[a][b]))
# Original solution
import queue 
N = int(eval(input()))
tree = [[]for _ in range(N+1)]
for i in range(1,N):
    a,b = list(map(int,input().split()))
    tree[a].append( [b,i])
    tree[b].append([a,i])

que = queue.Queue()
node = [-1]*(N+1)
edge = [-1]*N
que.put(1)
node[1] = 1
maxi = max([len(i) for i in tree])
color = [[i for i in range(1,maxi+1)] for _ in range(N+1)]
while(True):
    if que.empty():
        break
    start = que.get()
    for i in tree[start]:
        
        
        if edge[i[1]] == -1:
            col = max(color[i[0]][0],color[start][0])
            edge[i[1]] = col
            que.put(i[0])
            color[i[0]].remove(col)
            color[start].remove(col)
print(maxi)
for i in edge[1:]:
    print(i)

# Optimized solution
import queue 
N = int(eval(input()))
tree = [[]for _ in range(N+1)]
for i in range(1,N):
    a,b = list(map(int,input().split()))
    tree[a].append( [b,i])
    tree[b].append([a,i])
 
que = queue.Queue()
node = [-1]*(N+1)
edge = [-1]*N
que.put(1)
node[1] = 1
maxi = 1
color = [[] for _ in range(N+1)]
while(True):
    if que.empty():
        break
    start = que.get()
    for i in tree[start]:
        
        
        col = 1
        if edge[i[1]] == -1:
            que.put(i[0])
            while(True):
               
                if col in (color[i[0]] + color[start]):
                    col +=1
                    if col > maxi:
                        maxi = col
                else :
                    break
            edge[i[1]] = col
            color[i[0]].append(col)
            color[start].append(col)
print(maxi)
for i in edge[1:]:
    print(i)
# Original solution
from collections import deque
N = int(eval(input()))
edges = [[] for _ in range(N + 1)]
for edge_idx in range(1, N):
    a, b = list(map(int, input().split()))
    edges[a].append([edge_idx, b])
    edges[b].append([edge_idx, a])

used_edges = []
colors = [1 for _ in range(1, N + 1)]
used_colors = [[] for _ in range(N + 1)]
stack = deque([[edges[1], 0]])
max_col = 1

while stack:
    edge_info, parent_node_idx = stack.popleft()
    cur_color = 1
    for edge_idx, node_idx in edge_info:
        if edge_idx in used_edges: continue
        while cur_color in used_colors[node_idx] or cur_color in used_colors[parent_node_idx]:
            cur_color += 1
        used_colors[node_idx].append(cur_color)
        colors[edge_idx] = cur_color
        stack.append([edges[node_idx], node_idx])
        used_edges.append(edge_idx)
        max_col = max(max_col, cur_color)
        cur_color += 1
        
print(max_col)
for c in colors[1:]:
    print(c)


# Optimized solution
from collections import deque
N = int(eval(input()))
edges = [[] for _ in range(N + 1)]
for edge_idx in range(1, N):
    a, b = list(map(int, input().split()))
    edges[a].append([edge_idx, b])
    edges[b].append([edge_idx, a])

used_edges = set()
colors = [1 for _ in range(1, N + 1)]
used_colors = [set() for _ in range(N + 1)]
stack = deque([[edges[1], 0]])
max_col = 1

while stack:
    edge_info, parent_node_idx = stack.pop()
    cur_color = 1
    for edge_idx, node_idx in edge_info:
        if edge_idx in used_edges: continue
        while cur_color in used_colors[node_idx] or cur_color in used_colors[parent_node_idx]:
            cur_color += 1
        used_colors[node_idx].add(cur_color)
        colors[edge_idx] = cur_color
        stack.append([edges[node_idx], node_idx])
        used_edges.add(edge_idx)
        max_col = max(max_col, cur_color)
        cur_color += 1

print(max_col)
for c in colors[1:]:
    print(c)
# Original solution
n = int(eval(input()))
l = [[] for _ in range(n+1)]
s = [0 for _ in range(n+1)]
ll = []
for _ in range(n-1):
  ai,bi = list(map(int,input().split()))
  l[ai].append(bi)
  l[bi].append(ai)
  ll.append([ai,bi])
  s[ai] += 1
  s[bi] += 1
mx = 0
for i in range(1,n+1):
  if s[i] > mx:
    mx = s[i]
    mxi = i
print(mx)
ans = [[0 for _ in range(n+1)] for _ in range(n+1)]
def dfs(a,b,c):
  i = 1
  for h in l[a]:
    if h != b:
      if i == c:
        i += 1
      ans[a][h] = i
      ans[h][a] = i
      dfs(h,a,i)
      i += 1
  return
dfs(mxi,0,0)
for xx in ll:
  print((ans[xx[0]][xx[1]]))

# Optimized solution
import sys
import resource
sys.setrecursionlimit(10**5)
n = int(eval(input()))
l = [[] for _ in range(n+1)]
s = [0 for _ in range(n+1)]
ll = []
for i in range(n-1):
  ai,bi = list(map(int,input().split()))
  l[ai].append([bi,i])
  l[bi].append([ai,i])
  s[ai] += 1
  s[bi] += 1
mx = 0
for i in range(1,n+1):
  if s[i] > mx:
    mx = s[i]
    mxi = i
print(mx)
ans = [0 for _ in range(n-1)]
def dfs(a,b,c):
  i = 1
  for h,j in l[a]:
    if h != b:
      if i == c:
        i += 1
      ans[j] = i
      dfs(h,a,i)
      i += 1
  return
dfs(mxi,0,0)
for x in ans:
  print(x)
# Original solution
N = int(eval(input()))
edges = [[] for i in range(N)]
ans = [[0 for i in range(N + 1)] for i in range(N + 1)]
lines = []

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

q = [(0, 0,)]
max_color = 0
while q:
    v, color = q.pop()
    c = 0
    for nv in edges[v]:
        c += 1
        if c == color:
            c += 1
        q.append((nv, c,))
        ans[v + 1][nv + 1] = c
        max_color = max(max_color, c)

print(max_color)
for i in range(N - 1):
    a, b = lines[i]
    print((ans[a][b]))


# Optimized solution
N = int(eval(input()))
edges = [[] for i in range(N)]
ans = [-1] * (N - 1)
lines = []

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

q = [(0, 0,)]
max_color = 0
while q:
    v, c = q.pop()
    color = 1
    if c == color:
        color += 1
    for nv, i in edges[v]:
        ans[i] = color
        q.append((nv, color,))
        color += 1
        if c == color:
            color += 1

print((max(ans)))
for i in range(N - 1):
    a, b = lines[i]
    print((ans[i]))
# Original solution
import sys
input = sys.stdin.readline

N = int(eval(input()))
graph = [[] for _ in range(N)]
Ed = {}
for i in range(N-1):
    a, b = list(map(int, input().split()))
    graph[a-1].append(b-1)
    graph[b-1].append(a-1)
    Ed[(a-1)*N+b-1] = i
    Ed[(b-1)*N+a-1] = i

q = [0]
checked = [False]*N
checked[0] = True

V_color = [None]*N
V_color[0] = 0

ans = [None]*(N-1)
while q:
    qq = []
    for p in q:
        c = V_color[p]
        t = 1
        for np in graph[p]:
            if not checked[np]:
                checked[np] = True
                qq.append(np)
                ind = Ed[p*N+np]
                if t == c:
                    t += 1
                ans[ind] = t
                V_color[np] = t
                t += 1
    q = qq

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

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

N = int(eval(input()))
graph = [[] for _ in range(N)]
Edges = []
for _ in range(N-1):
    a, b = list(map(int, input().split()))
    graph[a-1].append(b-1)
    graph[b-1].append(a-1)
    Edges.append((a-1, b-1))

Col = 0
for n in range(N):
    Col = max(Col, len(graph[n]))

Color = dict()
checked = [-1]*N
q = [0]
checked[0] = Col+1
while q:
    qq = []
    for p in q:
        c = checked[p]
        t = 0
        for np in graph[p]:
            if checked[np] == -1:
                if t == c:
                    t += 1
                checked[np] = t
                Color[(p, np)] = t
                Color[(np, p)] = t
                t += 1
                qq.append(np)
    q = qq

print(Col)
for a, b in Edges:
    print((Color[(a, b)]+1))
# Original solution
import sys
sys.setrecursionlimit(10**8)

N = int(eval(input()))
adj = [[] for _ in range(N+1)]
for e in range(1,N):
  a,b = list(map(int, input().split()))
  adj[a].append((b,e))
  adj[b].append((a,e))

#print(adj)

col_num = max([len(ad) for ad in adj])
edge_color = [0]*N
visited = [False]*(N+1)

def dfs(v,e=-1):
  visited[v] = True
  #print(v,e,edge_color)
  col_lis = [i for i in range(1,col_num+1)]
  if e >0:
    col_lis.remove(edge_color[e])
  #color = 1
  for w,f in adj[v]:
    if visited[w]==False:
      #if c==color: color+=1
      edge_color[f] = col_lis.pop(0)
      dfs(w,f)
      #color+=1

dfs(1)

print(col_num)
for i in range(1,N):
  print((edge_color[i]))

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

def dfs(v,c):
  now = 1
  for u,i in edge[v]:
    if color[i]==0:
      if now==c:
        now += 1
      color[i] = now 
      dfs(u,now)
      now += 1
  return 0

N = int(input())
edge = [[] for _ in range(N)]
for i in range(N-1):
  a,b = map(int, input().split())
  edge[a-1].append([b-1,i])
  edge[b-1].append([a-1,i])
color = [0]*(N-1)
dfs(0,1<<30)
print(max(color))
print(*color, sep='\n')