using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

class Program
{
    static void Main(string[] args)
    {
        var waaaa = new waaaa();
        waaaa.Solve();
    }
}

public class waaaa
{
    const int MOD = 1000000007;
    const int INF = 1 << 20;
    const long INFL = 1 << 62;
    const int MOD2 = 998244353;

    myinout IO = new myinout();
    Math2 mmath = new Math2();




    public void Solve()
    {
        //ここから
        var n = IO.int1;
        var edge = Enumerable.Repeat(0, n).Select(_ => new List<int>()).ToArray();　//頂点vにつながる辺list
        var e = new Tuple<int, int>[n];　//from to
        for (int i = 0; i < n - 1; ++i)
        {
            var o = IO.intm;
            e[i] = new Tuple<int, int>(o[0]-1, o[1]-1);  
            edge[e[i].Item1].Add(i);  
            edge[e[i].Item2].Add(i);
        }

        var col = new int[n - 1];
        var q = new Queue<int>();
        q.Enqueue(0);
        while (q.Any())
        {
            int p = q.Dequeue();
            int pcol = 0;
            foreach (var item in edge[p]) //頂点につながる辺
            {
                if (col[item] > 0) //すでに彩色なら
                {
                    pcol = col[item];　//頂点pの色にする
                    break;
                }
            }
            int c = 1;
            foreach (var item in edge[p])
            {
                if (col[item] > 0) continue; //彩色してない辺について
                if (c == pcol) c++;　   //頂点と同じ色なら違う色にする
                col[item] = c;
                c++;
                q.Enqueue(e[item].Item1 + e[item].Item2 - p); //辺itemのfromの頂点+toの頂点-今の頂点(いま見てない方向に行きたい)
            }
        }

        int k = col.Max();
        IO.wri(k);
        foreach(var item in col) IO.wri(item);



    }



}

//b-aで降順

public class Math2
{
    public long[] fact;  //Nまでの階乗
    public long[] invfact;  //階乗の逆元

    //Nまでの階乗をセットしておく
    public void factoricalmodset(long N, long MOD = 1000000007)
    {
        fact = new long[N + 1];
        invfact = new long[N + 1];
        fact[0] = 1;

        for (long i = 1; i <= N; ++i)
        {
            fact[i] = fact[i - 1] * i % MOD;
        }
        invfact[N] = pow(fact[N], MOD - 2);

        for (long i = N; i > 0; --i)
        {
            invfact[i - 1] = invfact[i] * i % MOD;
        }

    }

    //nCr 引数:n r (mod)
    public long nCr(long n, long r, long MOD = 1000000007)
    {
        return (fact[n] * invfact[r] % MOD * invfact[n - r] % MOD);
    }

    //階乗(O(logN)) 引数:底x n乗　(MOD)
    public long pow(long i, long n, long MOD = 1000000007)
    {
        long res = 1;
        while (n > 0)
        {
            if ((n & 1) != 0) res = res * i % MOD;
            i = i * i % MOD;
            n >>= 1;
        }
        return res;
    }

    //最大公約数 引数:整数x,y
    public long gcd(long i, long y)
    {
        while (y != 0)
        {
            var r = i % y;
            i = y;
            y = r;
        }
        return i;
    }

    //最小公倍数 引数:整数x,y
    public long lcm(long i, long y)
    {
        return i * y / gcd(i, y);
    }

    //素因数分解 引数:整数N
    public Dictionary<long, int> primefactorization(long N)
    {
        var ret = new Dictionary<long, int>();

        for (long i = 2; i * i <= N; ++i)
        {
            int cnt = 0;
            while (N % i == 0)
            {
                cnt++;
                N /= i;
            }
            if (cnt != 0) ret[i] = cnt;

        }
        if (N >= 2) ret[N] = 1;

        return ret;

    }

    //約数列挙
    public List<long> divisorenumrate(long N)
    {
        var ret = new List<long>();

        for (long i = 1; i * i <= N; ++i)
        {

            if (N % i == 0)
            {
                ret.Add(i);
                ret.Add(N / i);
            }

        }

        return ret;

    }

    public void swap<T>(ref T a, ref T b)
    {
        var i = a;
        a = b;
        b = i;
    }

}

class myinout
{
    //in
    public string str => Console.ReadLine();

    public string[] strm => str.Split(' ');

    public long[] longm => strm.Select(long.Parse).ToArray();
    public int[] intm => strm.Select(int.Parse).ToArray();
    public char[] charm => str.ToArray();
    public long long1 => longm[0];
    public int int1 => intm[0];
    public char char1 => charm[0];

    //out
    public void wri<T>(T i)
    {
        Console.WriteLine(i);
    }

    public void yn(bool i)
    {
        if (i) wri("Yes");
        else wri("No");
    }

}


Measured memory_bytes: 29164