// ---------- begin chmin, chmax ----------
trait ChangeMinMax {
    fn chmin(&mut self, x: Self) -> bool;
    fn chmax(&mut self, x: Self) -> bool;
}

impl<T: PartialOrd> ChangeMinMax for T {
    fn chmin(&mut self, x: Self) -> bool {
        *self > x && {
            *self = x;
            true
        }
    }
    fn chmax(&mut self, x: Self) -> bool {
        *self < x && {
            *self = x;
            true
        }
    }
}
// ---------- end chmin, chmax ----------
// ---------- begin segment tree closure ----------
struct SegmentTree<T> {
    size: usize,
    val: Vec<Option<T>>,
}

#[allow(dead_code)]
impl<T> SegmentTree<T> 
where
    T: Clone
{
    fn new(size: usize) -> Self {
        let size = size.next_power_of_two();
        SegmentTree {
            size: size,
            val: (0..(2 * size)).map(|_| None).collect(),
        }
    }
    fn build_by<F>(a: &[T], mut f: F) -> Self
    where
        F: FnMut(&T, &T) -> T,
    {
        let size = a.len().next_power_of_two();
        let mut val = (0..(2 * size)).map(|_| None).collect::<Vec<_>>();
        for (v, a) in val[size..].iter_mut().zip(a.iter()) {
            *v = Some(a.clone());
        }
        for x in (1..size).rev() {
            val[x] = match (val[2 * x].as_ref(), val[2 * x + 1].as_ref()) {
                (Some(l), Some(r)) => Some(f(l, r)),
                _ => val[2 * x].clone().or_else(|| val[2 * x + 1].clone()),
            };
        }
        SegmentTree {
            size: size,
            val: val,
        }
    }
    fn update<F>(&mut self, x: usize, val: Option<T>, mut f: F)
    where
        F: FnMut(&T, &T) -> T,
    {
        assert!(x < self.size);
        let mut x = x + self.size;
        self.val[x] = val;
        let val = &mut self.val;
        x >>= 1;
        while x > 0 {
            val[x] = match (val[2 * x].as_ref(), val[2 * x + 1].as_ref()) {
                (Some(l), Some(r)) => Some(f(l, r)),
                _ => val[2 * x].clone().or_else(|| val[2 * x + 1].clone()),
            };
            x >>= 1;
        }
    }
    fn query<F>(&self, l: usize, r: usize, mut f: F)
    where
        F: FnMut(&T),
    {
        assert!(l <= r && r <= self.size);
        let mut l = self.size + l;
        let mut r = self.size + r;
        let val = &self.val;
        while l < r {
            if l & 1 == 1 {
                val[l].as_ref().map(|p| f(p));
                l += 1;
            }
            if r & 1 == 1 {
                r -= 1;
                val[r].as_ref().map(|p| f(p));
            }
            l >>= 1;
            r >>= 1;
        }
    }
}
// ---------- end segment tree closure ----------

use proconio::*;
use proconio::marker::*;
use std::cmp::*;

fn run() {
    input! {
        n: usize,
        m: usize,
        e: [(Usize1, usize, u64); m],
    }
    let ini = (0..n).collect::<Vec<_>>();
    let mut id = n;
    let mut gen = || {
        let v = id;
        id += 1;
        v
    };
    let mut edge = vec![];
    let up = SegmentTree::build_by(&ini, |a, b| {
        let v = gen();
        edge.push((*a, v, 0));
        edge.push((*b, v, 0));
        v
    });
    let down = SegmentTree::build_by(&ini, |a, b| {
        let v = gen();
        edge.push((v, *a, 0));
        edge.push((v, *b, 0));
        v
    });
    for (l, r, c) in e {
        let src = gen();
        let dst = gen();
        edge.push((src, dst, c));
        up.query(l, r, |v| {
            edge.push((*v, src, 0));
        });
        down.query(l, r, |v| {
            edge.push((dst, *v, 0));
        });
    }
    let size = gen();
    let mut cnt = vec![0; size];
    for &(s, _, _) in edge.iter() {
        cnt[s] += 1;
    }
    let mut g = cnt.into_iter().map(|c| Vec::with_capacity(c)).collect::<Vec<_>>();
    for (s, t, c) in edge {
        g[s].push((t, c));
    }
    let mut dp = vec![std::u64::MAX; size];
    dp[0] = 0;
    let mut h = std::collections::BinaryHeap::new();
    h.push(Reverse((0, 0)));
    while let Some(Reverse((d, v))) = h.pop() {
        if d > dp[v] {
            continue;
        }
        for &(u, c) in g[v].iter() {
            let d = d + c;
            if dp[u].chmin(d) {
                h.push(Reverse((d, u)));
            }
        }
    }
    let ans = dp[n - 1];
    if ans == std::u64::MAX {
        println!("-1");
    } else {
        println!("{}", ans);
    }
}

fn main() {
    run();
}


Measured memory_bytes: 158648