#include <stdio.h>
FILE *fin;
int poz, val;
char buff[ ( 1 << 15 ) ];
char nextChar() {
if( poz == sizeof( buff ) ) {
fread( buff, 1, sizeof( buff ), fin );
poz = 0;
}
return buff[ poz++ ];
}
bool f[ 100 ];
int readInt() {
int rez = 0, ch;
while( !f[ ch = nextChar() ] );
do
rez = rez * 10 + ch - '0';
while( f[ ch = nextChar() ] );
return rez;
}
#include <vector>
#include <bitset>
#include <queue>
#define MAX 30001
struct pp {
int val, cost;
};
std::vector<pp> noduri[ MAX + 1 ];
int n, m, X, Y;
std::bitset<MAX + 1> ok;
int dp[ MAX + 1 ];
std::queue<int> q;
void Lee() {
const int INF = ( 1 << 30 );
for( int i = 0; i <= n; i++ )
dp[ i ] = INF;
dp[ X ] = 0;
ok[ X ] = 1;
q.push( X );
while( !q.empty() ) {
int nod = q.front();
q.pop();
int Cost;
ok[ nod ] = 1;
int right = noduri[ nod ].size();
for( int i = 0; i < right; i++ ) {
if( nod < noduri[ nod ][ i ].val )
Cost = noduri[ nod ][ i ].cost;
else Cost = -noduri[ nod ][ i ].cost;
if( !ok[ noduri[ nod ][ i ].val ] && dp[ noduri[ nod ][ i ].val ] > dp[ nod ] + Cost ) {
dp[ noduri[ nod ][ i ].val ] = dp[ nod ] + Cost;
ok[ noduri[ nod ][ i ].val ] = 1;
q.push( noduri[ nod ][ i ].val );
}
}
}
}
int main()
{
////////////////////////////////////
val = sizeof( buff );
f[ '1' ] = f[ '2' ] = f[ '3' ] = f[ '4' ] = f[ '5' ] = 1;
f[ '6' ] = f[ '7' ] = f[ '8' ] = f[ '9' ] = f[ '0' ] = 1;
////////////////////////////////////
fin = fopen( "sate.in", "r" );
fread( buff, 1, sizeof( buff ), fin );
n = readInt();
m = readInt();
X = readInt();
Y = readInt();
int x, y, cost;
for( int i = 0; i < m; i++ ) {
x = readInt();
y = readInt();
cost = readInt();
noduri[ x ].push_back( { y, cost } );
noduri[ y ].push_back( { x, cost } );
}
fclose( fin );
Lee();
FILE *fout = fopen( "sate.out", "w" );
fprintf( fout, "%d\n", dp[ Y ] );
fclose( fout );
return 0;
}