unittest
{
	assert( [ "4 3 2 3", "1 4 1 100", "1 2 1 10", "1 3 20 1" ].parse.expand.solve == "999999999999998\n999999999999989\n999999999999979\n999999999999897" );
	assert( [ "8 12 3 8", "2 8 685087149 857180777", "6 7 298270585 209942236", "2 4 346080035 234079976", "2 5 131857300 22507157", "4 8 30723332 173476334", "2 6 480845267 448565596", "1 4 181424400 548830121", "4 5 57429995 195056405", "7 8 160277628 479932440", "1 6 475692952 203530153", "3 5 336869679 160714712", "2 7 389775999 199123879" ].parse.expand.solve == "999999574976994\n999999574976994\n999999574976994\n999999574976994\n999999574976994\n999999574976994\n999999574976994\n999999574976994" );
}



import std.algorithm;
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 nmst = input.front.split.to!( long[] );
	nmst[ 2 .. $ ] -= 1;
	auto uvabs = new long[ 4 ][ nmst[ 1 ] ];
	foreach( ref uvab; uvabs )
	{
		input.popFront;
		uvab = input.front.split.to!( long[] );
		uvab[ 0 .. 2 ] -= 1;
	}
	return tuple( nmst[ 0 ], nmst[ 2 ], nmst[ 3 ], uvabs );
}

auto solve( long n, long s, long t, long[ 4 ][] uvabs )
{
	// 都市sから各都市へ移動する最小コスト（円）を計算
	auto as = dijkstra!( true )( n, uvabs, 2, s );
	
	// 各都市から都市tへ移動する最小コスト（スヌーク）を計算
	auto bs = dijkstra!( true )( n, uvabs, 3, t );
	
	// 都市sから都市iへ移動して両替後に都市tへ移動する場合の最小コスト（円＋スヌーク）を計算
	auto anss = new long[ n ];
	auto m = long.max;
	foreach_reverse( i, ref ans; anss )
	{
		m = min( m, as[ i ] + bs[ i ] );
		ans = 10L ^^ 15 - m;
	}
	return anss.to!( string[] ).join( "\n" );
}

// 正の重み付きグラフの始点指定最短経路探索（ダイクストラ法）
auto dijkstra( bool undirected = false )( long n, long[ 4 ][] es, long c, long s )
{
	import std.container.binaryheap;
	
	auto ds = new long[ n ];
	ds[] = long.max;
	ds[ s ] = 0;
	auto us = new bool[ n ];
	auto uc = 0L;
	
	auto nss = new Tuple!( long, long )[][ n ];
	foreach( e; es )
	{
		nss[ e[ 0 ] ] ~= tuple( e[ 1 ], e[ c ] );
		static if( undirected ) nss[ e[ 1 ] ] ~= tuple( e[ 0 ], e[ c ] );
	}
	
	auto queue = heapify!( ( a, b ) => b[ 1 ] < a[ 1 ] )( new Tuple!( long, long )[ es.length ], 0 );
	queue.insert( tuple( s, 0L ) );
	while( !queue.empty )
	{
		auto fi = queue.front[ 0 ];
		auto fd = queue.front[ 1 ];
		queue.popFront();
		
		if( us[ fi ] ) continue;
		us[ fi ] = true;
		uc++;
		if( uc == us.length ) break;
		
		foreach( t; nss[ fi ] )
		{
			auto ti = t[ 0 ];
			auto td = fd + t[ 1 ];
			
			if( ds[ ti ] <= td ) continue;
			ds[ ti ] = td;
			queue.insert( tuple( ti, td ) );
		}
	}
	return ds;
}
