unittest
{
	assert( [ "4 3", "1 2", "2 3", "3 4" ].solve == 6 );
	assert( [ "5 4", "1 2", "1 3", "1 4", "4 5" ].solve == 48 );
	assert( [ "16 22", "12 1", "3 1", "4 16", "7 12", "6 2", "2 15", "5 16", "14 16", "10 11", "3 10", "3 13", "8 6", "16 8", "9 12", "4 3" ].solve == 271414432 );
	
	assert( [ "4 3", "1 2", "1 3", "1 4" ].solve == 0 );		// 追加ケース
}



import std.container;
import std.conv;
import std.format;
import std.range;
import std.stdio;

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

auto solve( Range )( Range input )
if( isInputRange!Range && is( ElementType!Range == string ) )
{
	auto n = 0L;
	auto k = 0L;
	input.front.formattedRead!"%s %s"( n, k );
	auto abs = new long[ 2 ][ n - 1 ];
	foreach( ref ab; abs )
	{
		input.popFront;
		ab = input.front.split.to!( long[] );
		ab[] -= 1;
	}
	
	// dfsで塗り方を探索（行きがけに塗り方パターン数を計算、帰りがけに塗り済隣接頂点を+1する）
	const M = 10L ^^ 9 + 7;
	auto ans = ModWorld!M( k );
	auto nss = toAdjacencyList!true( n, abs );
	auto cs = new long[ n ];
	auto stack = make!SList( 0L );
	while( !stack.empty )
	{
		auto f = stack.front;
		stack.removeFront;
		
		foreach( t; nss[ f ] )
		{
			if( 0 < cs[ t ] ) continue;
			
			auto p = k - cs[ f ] - 1;
			if( p <= 0 ) return ModWorld!M( 0 );
			
			ans *= p;
			cs[ t ] = 1;
			cs[ f ]++;
			stack.insertFront( t );
		}
	}
	return ans;
}

// 辺配列から隣接リストを作成
auto toAdjacencyList( bool undirected = false )( long n, long[ 2 ][] es )
{
	auto nss = new long[][ n ];
	foreach( e; es )
	{
		nss[ e[ 0 ] ] ~= e[ 1 ];
		static if( undirected ) nss[ e[ 1 ] ] ~= e[ 0 ];
	}
	return nss;
}

// モジュラ整数型（n mod M）
struct ModWorld( long M )
{
	long n;
	
	void opUnary( string OP )() if( OP == "++" ){ this.n = ( this.n + 1 ) % M; }
	void opUnary( string OP )() if( OP == "--" ){ this.n = ( this.n + M - 1 ) % M; }
	void opOpAssign( string OP )( ModWorld r ) if( OP == "+"  ){ this.n = ( this.n + r.n ) % M; }
	void opOpAssign( string OP )( ModWorld r ) if( OP == "-"  ){ this.n = ( this.n + M - r.n ) % M; }
	void opOpAssign( string OP )( ModWorld r ) if( OP == "*"  ){ this.n = ( this.n * r.n ) % M; }
	void opOpAssign( string OP )( ModWorld r ) if( OP == "/"  ){ this *= r ^^ ModWorld( M - 2 ); }
	void opOpAssign( string OP )( ModWorld r ) if( OP == "^^" )
	{
		auto a = this.n;
		this.n = 1L;
		for( auto i = r.n; 0 < i; i >>= 1 )
		{
			if( i & 1 ) this.n = ( this.n * a ) % M;
			a = ( a * a ) % M;
		}
	}
	auto opBinary( string OP )( ModWorld r ){ auto l = this; l.opOpAssign!OP( r ); return l; }
	
	void opAssign( long r ){ this.n = r; }
	void opOpAssign( string OP )( long r ){ this.opOpAssign!OP( ModWorld( r ) ); }
	auto opBinary( string OP )( long r ){ return this.opBinary!OP( ModWorld( r ) ); }
	auto opBinaryRight( string OP )( long l ){ return ModWorld( l ).opBinary!OP( this ); }
	auto opEquals( long r ){ return this.n == r; }
	
	auto toString(){ return this.n.to!string; }
}
