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.Collections;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using static System.Console;
using static System.Math;
 
public class Hello{
    static public int mod = 1000000007;
    public static void Main(){
        // 方針
        // 
        int n = rint();
        int[,] hen = inta2(n-1,2);
        var dic = new Dictionary<string,int>();
        int[] used = new int[n];
        var list = new List<List<int>>();
        for(int i=0;i<n;i++){
            list.Add(new List<int>());
        }
        for(int i=0;i<n-1;i++){
            hen[i,0]--;
            hen[i,1]--;
            list[hen[i,0]].Add(hen[i,1]);
            list[hen[i,1]].Add(hen[i,0]);
        }
        int max = 0;
        for(int i=0;i<n;i++){
            max = Max(max,list[i].Count);
        }
        WriteLine(max);
        for(int i=0;i<n-1;i++){
            if(i==0){
                int temp = 1;
                foreach(var k in list[i]){
                    string t = k.ToString()+" "+i.ToString();
                    string t2 = i.ToString()+" "+k.ToString();
                    used[k] = temp;
                    dic.Add(t,temp);
                    dic.Add(t2,temp);
                    temp++;
                }
            }else{
                foreach(var k in list[i]){
                    
                }
                int temp = 1;
                foreach(var k in list[i]){
                    string t = k.ToString()+" "+i.ToString();
                    string t2 = i.ToString()+" "+k.ToString();
                    if(dic.ContainsKey(t) || dic.ContainsKey(t2)) continue;
                    if(used[i] == temp) temp++;
                    used[k] = temp;
                    dic.Add(t,temp);
                    dic.Add(t2,temp);
                    temp++;
                }
            }
        }
        for(int i=0;i<n-1;i++){
            string t = hen[i,0].ToString()+" "+hen[i,1].ToString();
            WriteLine(dic[t]);
        }
        
        
        
        
    }
    static void unionfind(ref int[] uni,int a,int b){
        var memo = new List<int>();
        memo.Add(a);
        memo.Add(b);
        int min = Min(a,b);
        while(uni[a] != a){
            a = uni[a];
            memo.Add(a);
        }
        while(uni[b] != b){
            b = uni[b];
            memo.Add(b);
        }
        min = Min(min,a);
        min = Min(min,b);
        foreach(var k in memo){
            uni[k] = min;
        }
    }
    static int unionfind2(ref int[] uni,int a){
        var memo = new List<int>();
        memo.Add(a);
        while(uni[a] != a){
            a = uni[a];
            memo.Add(a);
        }
        foreach(var k in memo){
            uni[k] = a;
        }
        return a;
    }
    static int binarysearchd(int[] a,int b){
        int leng = a.Length;
        int min = 0;
        int max = leng-1;
        while(max - min > 1){
            int mid = (min+max)/2;
            if(a[mid] < b){
                min = mid;
            }else{
                max = mid;
            }
        }
        if(a[0] >= b){
            return 0;
        }else if(a[leng-1] < b){
            return leng;
        }else{
            if(a[max] < b){
                return max+1;
            }
            return min+1;
        }
    }
    static int binarysearchu(int[] a,int b){
        int leng = a.Length;
        int min = 0;
        int max = leng-1;
        while(max - min > 1){
            int mid = (min+max)/2;
            if(a[mid] < b){
                min = mid;
            }else{
                max = mid;
            }
        }
        if(a[0] > b){
            return leng;
        }else if(a[leng-1] <= b){
            return 0;
        }else{
            if(a[max] <= b){
                return leng-(max+1);
            }
            return leng-(min+1);
        }
    }
    // 1からaまでの数字並べ替え全通り返すやつ
    static List<string> permutation(int a){var list = new List<string>();if(a == 1){list.Add("1");return list;}else{foreach(var k in permutation(a-1)){var ch = k.ToCharArray();for(int i=0;i<=ch.Length;i++){string intemp = "";if(i == 0){intemp += a.ToString();}for(int j=0;j<ch.Length;j++){intemp += ch[j].ToString();if(i == j+1){intemp += a.ToString();}}list.Add(intemp);}}}return list;}
    static void swap(ref int a,ref int b){int temp = a;a= b;b = temp;}
    static void charswap(ref char a,ref char b){char temp = a;a= b;b = temp;}
    static int ncr(int n,int r){r = Min(r,n-r);long nn = 1;for(int i=n-r+1;i<=n;i++){nn = nn*i%mod;}long rr = 1;for(int i=1;i<=r;i++){rr = rr*i%mod;}rr = square((int)rr,mod-2);nn = nn * rr %mod;return (int)nn;}
    // a^b mod
    static int square(int a,int b){string binary = Convert.ToString(b,2);int bileng = binary.Length;long a_power = a;long value = 1;for(int i=bileng-1;i>=0;i--){if(binary[i] == '1'){value = value*a_power%mod;}a_power = a_power*a_power%mod;}return (int)value;}
    static int square2(int a,int b){long output = 1;var list = new List<long>();int sh = 1;long n = a;list.Add(a);while(sh < b){sh *= 2;n = n*n%mod;list.Add(n);}for(int i=list.Count-1;i>=0;i--){if(b > sh){b -= sh;sh /= 2;output = output*list[i]%mod;}}return (int)output;}
    //各種読取
    static string rstr(){ return ReadLine(); }
    static int rint(){ return int.Parse(ReadLine()); }
    static long rlong(){ return long.Parse(ReadLine()); }
    static string[] stra(){ return ReadLine().Split(' '); }
    static char[] chara(){ string[] a=stra();string b="";for(int i=0;i<a.Length;i++){b+=a[i];}return b.ToCharArray();}
    static int[] inta(){ string[] read_str_array = ReadLine().Split(' '); int[] return_int_array = new int[read_str_array.Length]; for(int countup_i=0;countup_i<read_str_array.Length;countup_i++){ return_int_array[countup_i] = int.Parse(read_str_array[countup_i]); } return return_int_array; }
    static int[,] inta2(int num_array,int in_array){ int[,] int_array2 = new int[num_array,in_array]; for(int i=0;i<num_array;i++){ int[] temp_array = inta(); for(int j=0;j<in_array;j++){ int_array2[i,j] = temp_array[j]; } } return int_array2; }
    static long[] longa(){ string[] read_str_array = ReadLine().Split(' '); long[] return_long_array = new long[read_str_array.Length]; for(long countup_i=0;countup_i<read_str_array.Length;countup_i++){ return_long_array[countup_i] = long.Parse(read_str_array[countup_i]); } return return_long_array; }
    static double[] doublea(){ string[] read_str_array = ReadLine().Split(' '); double[] return_double_array = new double[read_str_array.Length]; for(long countup_i=0;countup_i<read_str_array.Length;countup_i++){ return_double_array[countup_i] = long.Parse(read_str_array[countup_i]); } return return_double_array; }
    // -----------------------------
    static long divideup(long divided,long divid){ long temp_divide = divided/divid; if(divided % divid > 0){ temp_divide++; } return temp_divide; }
    static long GCD(long a,long b){ if(a < b){ long temp = a; a = b; b = temp; } if(a % b == 0){ return b; } else{ long temp = b; b = a%b; a = temp; return GCD(a,b); } }
    static long LCM(long a,long b){ return a * b / GCD(a,b); }
}


//知見
// (string) hogestr -> (char[]) hoge
    // char hoge = hogestr.ToCharArray();
// (char[]) hoge -> (string) hogestr
    // string hoge = new string(hoge);
// Hashtable ×  Dictionary ○
// Dictionary hoge<string,int>
    // hoge.ContainsKey(string) -> return boolean
    // hoge[string] -> return int
    // hoge[int] -> CE
// Dictionary hoge<int1,int2>
    // hoge<int1,int2>: hoge[int1] -> return int2
    // KeyValuePair<int,int> k <-> k.Key == int1 / k.Value == int2
// SortedDictionary() > SortedList() ???
// キュー　-> 幅優先 ???
    // var queue = new Queue<int>(); queue.Enqueue() queue.Dequeue()
// スタック -> 深さ優先 ???
    // var stack = new Stack<int>(); stack.Push(hoge) stack.Pop() stackPeek() stack.Count
// if (list?.Count > 0) リストが空でもnullでもない
// ソート
    // list.Sort(StringComparer.Ordinal); listの(辞書順?)ソート
        // StringComparer.Ordinal とは
    // Array.Sort(list1,list2);
// 出力
    // foreach(var a int list){ WriteLine(a); } より
        // WriteLine(string.Join("\n", list)); が速い
    //var sw = new StreamWriter(Console.OpenStandardOutput()){AutoFlush = false};
    //    Console.SetOut(sw);
    //    foreach(var k in list[num-1]){
    //        WriteLine(k);
    //    }
    //    Console.Out.Flush();
// 未知
    // 最小費用流