//#include"holiday.h"
#include <bits/stdc++.h>
#define ll long long
#define rep(i,m,n) for(int i=(m); i<=(n); i++)
#define REB(i,m,n) for(int i=(m); i>=(n); i--)
#define pii pair<int,int>
#define pll pair<ll,ll>
#define MP make_pair
#define fs first
#define se second
#define bit(msk, i) ((msk >> i) & 1)
#define iter(id, v) for(auto id : v)
#define pb push_back
#define SZ(v) (ll)v.size()
#define ALL(v) v.begin(),v.end()
using namespace std;
mt19937_64 rd(chrono :: steady_clock :: now ().time_since_epoch().count());
ll Rand (ll l, ll r) { return uniform_int_distribution<ll> (l, r) (rd); }
const int N = 3e5 + 7;
const int Mod = 1e9 + 7;///lon
const ll INF = 1e18 + 7;
const ll BASE = 137;
const int szBL = 450;
struct Edge {
    int u, v, w;
};
int n, m;
int a[N];
Edge edges[N];
ll dp[2][N];
int Cost[N];
vector<pll> ke[N], adj[N];
int low[N], num[N];
void solution() {
    cin >> n >> m;
    rep (i, 1, m) {
        int u, v, w;
        cin >> u >> v >> w;
        ke[u].pb({v, w});
        ke[v].pb({u, w});
        edges[i] = {u, v, w};
    }
    REB (i, m, 1) {
        Cost[i] = max(edges[i].w, Cost[i + 1]);
    }
    memset(dp, 0x3f, sizeof dp);
    auto Dijkstra = [&] (int st, int typ) {
        vector<int> vis(n + 3, 0);
        priority_queue<pll, vector<pll>, greater<pll>> pq;
        pq.push({0, st});
        dp[typ][st] = 0;
        while (!pq.empty()) {
            int u = pq.top().se;
            pq.pop();
            if (vis[u]) continue;
            vis[u] = 1;
            iter (&id, ke[u]) {
                int v = id.fs, w = id.se;
                if (dp[typ][v] > dp[typ][u] + w) {
                    dp[typ][v] = dp[typ][u] + w;
                    pq.push({dp[typ][v], v});
                }
            }
        }
    };
    Dijkstra(1, 0);
    Dijkstra(n, 1);
    auto check = [&] (ll X)  {
        rep (i, 1, n) vector<pll> ().swap(adj[i]);
        rep (i, 1, m) {
            int u = edges[i].u, v = edges[i].v, w = edges[i].w;
            if (dp[0][u] + dp[1][v] + w < X || dp[0][v] + dp[1][u] + w < X) {
                adj[u].pb({v, w + Cost[i + 1]});
                adj[v].pb({u, w + Cost[i + 1]});
            }
        }
        rep (i, 1, n) low[i] = num[i] = 0;
        int res = 0;
        int time_dfs = 0;
        function<void(int, int)> dfs = [&] (int u, int p) {
            low[u] = num[u] = ++time_dfs;
            iter (&id, adj[u]) {
                int v = id.fs;
                ll w = id.se;
                if (v == p) continue;
                if (!num[v]) {
                    dfs(v, u);
                    low[u] = min(low[u], low[v]);
                    if (low[v] == num[v] && num[v] <= num[n]) {
                        if (dp[0][u] + dp[1][v] + w >= X) res = 1;
                    }
                }
                else {
                    low[u] = min(low[u], num[v]);
                }
            }
        };
        dfs(1, 0);
        if (!num[n]) return 1;
        return res;
    };
    ll L = dp[0][n], R = dp[0][n] * 2 + Cost[1];
    while (L < R) {
        ll mid = L + R + 1 >> 1;
        if (check(mid)) L = mid;
        else R = mid - 1;
    }
    cout << L <<"\n";
}
#define file(name) freopen(name".inp","r",stdin); \
freopen(name".out","w",stdout);
int main () {
//    file("c");
    ios_base :: sync_with_stdio(false); cin.tie(0); cout.tie(0);
    int num_Test = 1;
//    cin >> num_Test;
    while (num_Test--)
        solution();
}
/*
no bug challenge +33
2 1
0 1
*/
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... |