unittest
{
	assert( [ "5 4 1", "1 2", "2 3", "3 4", "3 5" ].parse.expand.solve == 2 );
	assert( [ "5 4 5", "1 2", "1 3", "1 4", "1 5" ].parse.expand.solve == 1 );
	assert( [ "2 1 2", "1 2" ].parse.expand.solve == 0 );
	assert( [ "9 6 1", "1 2", "2 3", "3 4", "4 5", "5 6", "4 7", "7 8", "8 9" ].parse.expand.solve == 5 );
}



import std.algorithm;
import std.container;
import std.conv;
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 nuv = input.front.split.to!( long[] );
	nuv[ 1 .. $ ] -= 1;
	auto abs = new long[ 2 ][ nuv[ 0 ] - 1 ];
	foreach( ref ab; abs )
	{
		input.popFront;
		ab = input.front.split.to!( long[] );
		ab[] -= 1;
	}
	return tuple( nuv[ 0 ], nuv[ 1 ], nuv[ 2 ], abs );
}

auto solve( long n, long u, long v, long[ 2 ][] abs )
{
	// 辺配列から隣接リストを作成
	auto nss = new long[][ n ];
	foreach( ab; abs )
	{
		nss[ ab[ 0 ] ] ~= ab[ 1 ];
		nss[ ab[ 1 ] ] ~= ab[ 0 ];
	}
	
	// 青木君の移動をシミュレート
	auto as = new long[ n ];
	as[] = -1;
	as[ v ] = 0;
	auto queue_a = make!DList( v );
	while( !queue_a.empty )
	{
		auto f = queue_a.front;
		queue_a.removeFront;
		
		foreach( t; nss[ f ] )
		{
			if( 0 <= as[ t ] ) continue;
			as[ t ] = as[ f ] + 1;
			queue_a.insertBack( t );
		}
	}
	
	// 高橋君の移動をシミュレート
	auto ans = 0L;
	auto ts = new long[ n ];
	ts[] = -1;
	ts[ u ] = 0;
	auto queue_t = make!DList( u );
	while( !queue_t.empty )
	{
		auto f = queue_t.front;
		queue_t.removeFront;
		
		auto d = ts[ f ] + 1;
		foreach( t; nss[ f ] )
		{
			if( 0 <= ts[ t ] ) continue;
			if( as[ t ] <= d )
			{
				// 捕まった
				ans = max( ans, as[ t ] );
			}
			else
			{
				// 捕まってない
				ts[ t ] = d;
				queue_t.insertBack( t );
			}
		}
	}
	
	// 行き止まりまで捕まらずに来れたら、うろうろして時間稼ぎする
	foreach( i, d; ts )
	{
		if( nss[ i ].length != 1 || d < 0 ) continue;
		ans = max( ans, as[ nss[ i ][ 0 ] ] );		// 絶対行き止まりの一つ前で捕まるので計算しなくていい
	}
	
	return ans;
}
