using System;
using System.Text;
using System.Collections.Generic;
using static System.Math;
using System.Linq;
using static System.Array;

namespace DigitsParades
{

    class Programk
    {
        static int N;
        static Node[] Nodes;
        static int Max = 0;
        static Dictionary<Tuple<int, int>, int> bridge;
        static void Main(string[] args)
        {
            N = int.Parse(Console.ReadLine());
            Nodes = new Node[N + 1];
            for (int i = 1; i < N + 1; i++)
            {
                Nodes[i] = new Node();
            }

            bridge = new Dictionary<Tuple<int, int>, int>();
            for (int i = 0; i < N - 1; i++)
            {
                var AB = Console.ReadLine().Split(' ').Select(x => int.Parse(x)).ToArray();
                var A = AB[0];
                var B = AB[1];
                Nodes[A].adj.Add(B);
                bridge.Add(new Tuple<int, int>(A, B), 0);
            }
            DFS();
            Console.WriteLine(Max);
            foreach (var item in bridge)
            {
                Console.WriteLine(item.Value);
            }


        }

        static void DFS()
        {
            var stack = new Stack<int>();
            stack.Push(1);
            Nodes[1].sumi = true;
            //スタックがからになるまで
            while (stack.Count > 0)
            {
                var now = stack.Pop();
                var peek = Nodes[now];
                foreach (var item in peek.adj)
                {
                    var chi = Nodes[item];
                    //var B = Max(now, item);
                    //var A = Min(now, item);
                    //探索済であるかどうか
                    if (!chi.sumi)
                    {
                        //色を決定する
                        while (peek.NG == peek.count)
                        {
                            peek.count++;
                        }
                        //端の情報を格納する
                        bridge[new Tuple<int, int>(now, item)] = peek.count;
                        //使用状況を格納する
                        //peek.used[peek.count] = true;
                        //chi.used[peek.count] = true;
                        chi.NG = peek.count;
                        //スタックにあらたに格納する
                        Max = Max(Max, peek.count);
                        chi.sumi = true;
                        stack.Push(item);
                        peek.count++;

                    }
                }
            }
        }
    }

    class Node
    {
        public bool sumi = false; 
        public int count = 1;
        public List<int> adj = new List<int>();
        public int NG = 0;
        //使用可能な色
        //public bool[] used;
        //public Node(int N)
        //{
        //    used = new bool[5000];
        //}
    }

    #region スキャナー
    class Scanner
    {
        public Scanner()
        {
            _pos = 0;
            _line = new string[0];
        }

        const char Separator = ' ';
        private int _pos;
        private string[] _line;

        #region スペース区切りで取得

        public string Next()
        {
            if (_pos >= _line.Length)
            {
                _line = Console.ReadLine().Split(Separator);
                _pos = 0;
            }

            return _line[_pos++];
        }

        public int NextInt()
        {
            return int.Parse(Next());
        }

        public int Nextint()
        {
            return int.Parse(Next());
        }

        public double NextDouble()
        {
            return double.Parse(Next());
        }

        #endregion

        #region 型変換

        private int[] ToIntArray(string[] array)
        {
            var result = new int[array.Length];
            for (int i = 0; i < array.Length; i++)
            {
                result[i] = int.Parse(array[i]);
            }

            return result;
        }

        private int[] TointArray(string[] array)
        {
            var result = new int[array.Length];
            for (int i = 0; i < array.Length; i++)
            {
                result[i] = int.Parse(array[i]);
            }

            return result;
        }

        private double[] ToDoubleArray(string[] array)
        {
            var result = new double[array.Length];
            for (int i = 0; i < array.Length; i++)
            {
                result[i] = double.Parse(array[i]);
            }

            return result;
        }

        #endregion

        #region 配列取得

        public string[] Array()
        {
            if (_pos >= _line.Length)
                _line = Console.ReadLine().Split(Separator);

            _pos = _line.Length;
            return _line;
        }

        public int[] IntArray()
        {
            return ToIntArray(Array());
        }

        public int[] intArray()
        {
            return TointArray(Array());
        }

        public double[] DoubleArray()
        {
            return ToDoubleArray(Array());
        }

        #endregion
    }
    #endregion  

}


Measured memory_bytes: 40320