Problem: Problem

There are N islands and M bridges. Numbers from 1 to N are assigned to each of the N islands. Numbers from 1 to M are also assigned to each of the M bridges.

Gaccho is currently on the first island (at time 0). Gaccho can move from the ai-th island to the bi-th island in one direction by using the i-th bridge.

However, at time 0, all the bridges were full of tide and sank into the sea. The i-th bridge will be able to cross the tide at time ci. And soon after the time ci, the tide rises again and the i-th bridge sinks again. When it sinks again, I don't know when the tide will pull and cross. So, Gaccho decided to think that such a bridge would never be crossed.

Gaccho wants to see the scenery of the 1st to N-1st islands for as long as possible, but since he is staying at the Nth island, he finally arrives at the Nth island. There must be. Also, because he keeps his parents waiting on the boat, Gacho must leave by boat and go home as soon as he arrives at the Nth island.

The time it takes for Gaccho to cross the bridge and travel around the island is very short, so you can assume it is 0. Find the maximum amount of time Gaccho can be on any of the 1st to N-1 islands. However, if you can't move to the Nth island no matter how you move, output -1 instead.

Constraints

* 2 ≤ N ≤ 105
* 1 ≤ M ≤ 2 × 105
* 1 ≤ ai <N
* 1 ≤ bi ≤ N
* 1 ≤ ci ≤ 109
* ai ≠ bi

Input

The input is given in the following format.


N M
a1 b1 c1
a2 b2 c2
...
aM bM cM


On the first line, two integers N and M are given, separated by blanks.
Three integers ai, bi, ci are given in each line i from the second line to the M + 1 line, separated by blanks.

Output

If Gaccho can move to the Nth island, it will output the maximum amount of time that Gaccho can be on any of the 1st to N-1th islands. If it cannot move to the Nth island, it prints -1 instead.

Examples

Input

3 2
1 2 10
2 3 20


Output

20


Input

4 4
1 2 27
1 3 37
2 3 47
3 1 57


Output

-1


Input

3 3
1 2 13
2 3 17
2 3 15


Output

17


Input

3 2
1 2 20
2 3 10


Output

-1


Input

3 2
1 2 10
2 3 10


Output

10

Solution (in CPP):

Solution:
#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;
}