unittest
{
	assert( [ "3", "1 2", "2 3" ].parse.expand.solve == "2\n1\n2" );
	assert( [ "8", "1 2", "2 3", "2 4", "2 5", "4 7", "5 6", "6 8" ].parse.expand.solve == "4\n1\n2\n3\n4\n1\n1\n2" );
	assert( [ "6", "1 2", "1 3", "1 4", "1 5", "1 6" ].parse.expand.solve == "5\n1\n2\n3\n4\n5" );
}



import std.algorithm;
import std.conv;
import std.format;
import std.range;
import std.stdio;
import std.typecons;

void main()
{
	stdin.byLineCopy.parse.expand.solve.writeln;
}

auto parse( Range )( Range input )
if( isInputRange!Range && is( ElementType!Range == string ) )
{
	auto n = input.front.to!( long );
	auto abs = new long[ 2 ][ n - 1 ];
	foreach( ref ab; abs )
	{
		input.popFront;
		ab = input.front.split.to!( long[] );
		ab[] -= 1;
	}
	return tuple( n, abs );
}

auto solve( long n, long[ 2 ][] abs )
{
	auto abis = new long[ 3 ][ abs.length ];
	foreach( i, ab; abs )
	{
		abis[ i ][ 0 .. 2 ] = ab;
		abis[ i ][ 2 ] = i;
	}
	abis.sort();
	
	auto m = 0L;
	auto p = 0L;
	auto pcs = new long[ n ];
	auto bcs = new long[ abs.length ];
	auto c = 1L;
	foreach( i, abi; abis )
	{
		if( abi[ 0 ] != p )
		{
			p = abi[ 0 ];
			c = 1L;
		}
		c += ( c == pcs[ abi[ 0 ] ] );
		pcs[ abi[ 1 ] ] = c;
		bcs[ abi[ 2 ] ] = c;
		m = max( m, c );
		c++;
	}
	return format( "%s\n%s", m, bcs.to!( string[] ).join( "\n" ) );
}
