#include<iostream>
#include<string>
#include<cstdio>
#include<vector>
#include<cmath>
#include<algorithm>
#include<functional>
#include<iomanip>
#include<queue>
#include<ciso646>
#include<utility>
#include<map>
#include<complex>
using namespace std;
typedef long long ll;
const ll mod = 1000000007;
const ll INF = mod * mod;
typedef pair<int, int> P;
typedef pair<ll, ll> LP;
typedef vector<int> vec;
#define rep(i,n) for(int i=0;i<n;i++)
#define Rep(i,sta,n) for(int i=sta;i<n;i++)
#define stop char nyaa;cin>>nyaa;
#define per(i,n) for(int i=n-1;i>=0;i--)

//geometry
typedef long double ld;
typedef complex<ld> Point;
const ld pi = acos(-1.0);
ld dot(Point a, Point b) { return real(conj(a)*b); }
ld cross(Point a, Point b) { return imag(conj(a)*b); }

struct Line {
	Point a, b;
};

Point is_ll(Line s, Line t) {
	Point sv = s.b - s.a;
	Point tv = t.b - t.a;
	return s.a + sv * cross(tv, t.a - s.a) / cross(tv, sv);
}

vector<int> ans;
//scc
struct graph {
private:
	int n; vector<vector<int>> G, rG;
	vector<bool> used;
	vector<int> vs;

	int mk;
	vector<vector<int>> fG;
	vector<vector<int>> ori;
	vector<int> trans;
public:
	graph(int sz) {
		n = sz;
		G.resize(n);
		rG.resize(n);
		used.resize(n);

		fG.resize(n);
		trans.resize(n, -1);
		ori.resize(n);
	}
	void add_edge(int a, int b) {
		G[a].push_back(b);
		rG[b].push_back(a);
	}
	void dfs(int v) {
		used[v] = true;
		rep(i, G[v].size()) {
			if (!used[G[v][i]])dfs(G[v][i]);
		}
		vs.push_back(v);
	}
	void rdfs(int v, int k) {
		used[v] = true;
		queue<int> q;
		q.push(v);
		vector<int> c;
		while (!q.empty()) {
			int id = q.front(); q.pop();
			ori[k].push_back(id);
			rep(j, rG[id].size()) {
				int to = rG[id][j];
				if (used[to]) {
					if (trans[to] >= 0)c.push_back(trans[to]);
					continue;
				}
				used[to] = true; q.push(to);
			}
		}
		sort(c.begin(), c.end());
		int len = unique(c.begin(), c.end()) - c.begin();
		rep(i, len) {
			fG[c[i]].push_back(k);
		}
		rep(i, ori[k].size()) {
			trans[ori[k][i]] = k;
		}
	}
	void scc() {
		fill(used.begin(), used.end(), false);
		rep(i, n)if (!used[i])dfs(i);
		fill(used.begin(), used.end(), false);
		int k = 0;
		per(i, (int)vs.size()) {
			if (!used[vs[i]]) {
				rdfs(vs[i], k); k++;
			}
		}
		mk = k;
	}
	void query(vector<int> &x,int &cur,int &sz) {
		vector<int> c(mk, 0);
		vector<int> val(mk, -1);
		rep(i, mk) {
			rep(j, ori[i].size()) {
				val[i] = max(val[i], ans[x[ori[i][j]]]);
				if (x[ori[i][j]] == sz - 1) {
					val[i] = max(val[i], cur);
				}
			}
		}
		rep(i, mk) {
			rep(j, fG[i].size()) {
				int to = fG[i][j];
				c[to]++;
			}
		}
		queue<int> q;
		rep(i, mk)if (c[i] == 0)q.push(i);
		while (!q.empty()) {
			int id = q.front(); q.pop();
			rep(j, fG[id].size()) {
				int to = fG[id][j]; c[to]--;
				if (c[to] == 0) {
					q.push(to);
				}
				val[to] = max(val[to], val[id]);
			}
		}
		rep(i, mk) {
			rep(j, ori[i].size()) {
				if (x[ori[i][j]] == sz - 1)continue;
				ans[x[ori[i][j]]] = val[i];
			}
		}
	}
};


void to_unique(vector<int> &v) {
	sort(v.begin(), v.end());
	v.erase(unique(v.begin(), v.end()), v.end());
}
void solve() {
	int n, m; cin >> n >> m;
	ans.resize(n, -1);
	vector<pair<int, P>> v;
	rep(i, m) {
		int a, b, c; cin >> a >> b >> c;
		a--; b--;
		if (a == n - 1)continue;
		v.push_back({ c,{ b,a } });
	}
	sort(v.begin(), v.end(), greater<pair<int,P>>());
	rep(i, v.size()) {
		int le = i;
		while (i + 1 < (int)v.size() && v[i].first == v[i + 1].first) {
			i++;
		}
		if (i == le) {
			int id = v[i].second.first; int to = v[i].second.second;
			ans[to] = max(ans[to], ans[id]);
			if (id == n - 1)ans[to] = max(ans[to], v[i].first);
			continue;
		}
		vector<int> x;
		vector<P> u;
		Rep(j, le, i+1) {
			u.push_back(v[j].second);
			x.push_back(v[j].second.first);
			x.push_back(v[j].second.second);
		}
		to_unique(x);
		{
			map<int, int> mp;
			rep(j, x.size()) {
				mp[x[j]] = j;
			}
			rep(j, u.size()) {
				u[j].first = mp[u[j].first];
				u[j].second = mp[u[j].second];
			}
		}
		graph g(x.size());
		rep(j, u.size()) {
			//cout << x[u[j].first] << " " << x[u[j].second] << endl;
			g.add_edge(u[j].first, u[j].second);
		}
		g.scc(); g.query(x,v[i].first,n);
	}
	//rep(i, n)cout << ans[i] << endl;
	cout << ans[0] << endl;
}


signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout << fixed << setprecision(10);
	solve();
	//stop
		return 0;
}



Measured memory_bytes: 20572