#include <iostream>
#include <vector>
#include <queue>
#include <stack>
#include <cmath>
#include <stack>
#include <algorithm>
#include <fstream>
using namespace std;
struct Edge {
int to;
int cost;
};
struct Node {
int n = -1;
vector<Edge> Adj;
bool IsAdjTo(int v) {
for (auto& i : Adj) {
if (i.to == v) {
return true;
}
}
return false;
}
};
struct Graph {
private:
bool Oriented;
bool Weighted;
vector<Node> Nodes;
int edgeCount = 0;
public:
Graph(bool _Oriented = true, bool _Weighted = false) {
Oriented = _Oriented;
Weighted = _Weighted;
}
void SetOriented(bool _Oriented) {
Oriented = _Oriented;
}
void SetNodeCount(int n) {
Nodes.resize(n);
for (int i = 0; i < n; i++) {
Nodes[i].n = i;
}
}
int GetNodeCount() {
return Nodes.size();
}
Node& operator[] (int i) {
return Nodes[i];
}
void AddEdge(int u, int v, int w = 1) {
Nodes[u].Adj.push_back({.to = v, .cost = w});
if (!Oriented)
Nodes[v].Adj.push_back({.to = u, .cost = w});
edgeCount++;
}
vector<Edge>& GetEdges(int u) {
return Nodes[u].Adj;
}
int GetEdgeCount() const {
return edgeCount;
}
};
#define in fin
#define out fout
ifstream fin("sate.in");
ofstream fout("sate.out");
void ReadMEdges(Graph &G, int M) {
while (M--) {
int u, v;
in >> u >> v;
G.AddEdge(u-1, v-1);
}
}
void ReadGraph(Graph &G, int N, int M) {
G.SetNodeCount(N);
ReadMEdges(G, M);
}
int calc_dist_xy(Graph &G) {
vector<int> dist(G.GetNodeCount(), -1);
queue<int> q;
q.push(0);
dist[0] = 0;
while (!q.empty()) {
int u = q.front();
q.pop();
for (auto& i : G.GetEdges(u)) {
if (dist[i.to] == -1) {
dist[i.to] = dist[u] + i.cost;
q.push(i.to);
}
}
}
return dist[G.GetNodeCount()-1];
}
int main() {
Graph G;
G.SetOriented(true);
int N, M;
in >> N >> M;
int X, Y;
in >> X >> Y;
G.SetNodeCount(N);
while (M--) {
int u, v, w;
in >> u >> v >> w;
G.AddEdge(u-1, v-1, w);
G.AddEdge(v-1, u-1, -w);
}
auto d = calc_dist_xy(G);
out << d << '\n';
}