Problem:
Score : 400 points

Problem Statement

Given is a tree G with N vertices.
The vertices are numbered 1 through N, and the i-th edge connects Vertex a_i and Vertex b_i.

Consider painting the edges in G with some number of colors.
We want to paint them so that, for each vertex, the colors of the edges incident to that vertex are all different.

Among the colorings satisfying the condition above, construct one that uses the minimum number of colors.

Constraints

2 \le N \le 10^5

1 \le a_i \lt b_i \le N

All values in input are integers.

The given graph is a tree.

Input

Input is given from Standard Input in the following format:

N
a_1 b_1
a_2 b_2
\vdots
a_{N-1} b_{N-1}

Output

Print N lines.

The first line should contain K, the number of colors used.

The (i+1)-th line (1 \le i \le N-1) should contain c_i, the integer representing the color of the i-th edge, where 1 \le c_i \le K must hold.

If there are multiple colorings with the minimum number of colors that satisfy the condition, printing any of them will be accepted.

Sample Input 1

3
1 2
2 3

Sample Output 1

2
1
2

Sample Input 2

8
1 2
2 3
2 4
2 5
4 7
5 6
6 8

Sample Output 2

4
1
2
3
4
1
1
2

Sample Input 3

6
1 2
1 3
1 4
1 5
1 6

Sample Output 3

5
1
2
3
4
5

Solution in C# (Mono 4.6.2.0) (judge verdict: Accepted)

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  

}