fn getline() -> String {
    let mut res = String::new();
    std::io::stdin().read_line(&mut res).ok();
    res
}

#[allow(unused_macros)]
macro_rules! readl {
    ($t: ty) => {
        {
            let s = getline();
            s.trim().parse::<$t>().unwrap()
        }
    };
    ($( $t: ty),+ ) => {
        {
            let s = getline();
            let mut iter = s.trim().split(' ');
            ($(iter.next().unwrap().parse::<$t>().unwrap(),)*)
        }
    };
}

#[allow(unused_macros)]
macro_rules! readlvec {
    ($t: ty) => {
        {
            let s = getline();
            let iter = s.trim().split(' ');
            iter.map(|x| x.parse().unwrap()).collect::<Vec<$t>>()
        }
    }
}

#[allow(unused_macros)]
macro_rules! debug {
    ($x: expr) => {
        println!("{}: {:?}", stringify!($x), $x)
    }
}

fn printiter<'a, T>(v: &'a T)
where
    &'a T: std::iter::IntoIterator,
    <&'a T as std::iter::IntoIterator>::Item: std::fmt::Display,
{
    for (i, e) in v.into_iter().enumerate() {
        if i != 0 {
            print!(" ");
        }
        print!("{}", e);
    }
    println!("");
}

mod algebra {
    use std::ops::{Add, Div, Mul, Neg, Sub};
    use std;

    pub trait Zero {
        fn zero() -> Self;
    }

    pub trait Monoid: Add<Self, Output = Self> + Zero
    where
        Self: std::marker::Sized,
    {}

    pub trait Group: Monoid + Neg<Output = Self> + Sub<Self, Output = Self> {}

    pub trait Ring: Group + One + Mul<Self, Output = Self> {}

    pub trait One {
        fn one() -> Self;
    }

    pub trait Field: Ring + Div<Self, Output = Self> {}
    
    impl<T: Add<T, Output = T> + Zero> Monoid for T {}
    impl<T: Monoid + Neg<Output = T> + Sub<T, Output = T>> Group for T {}
    impl<T: Group + One + Mul<T, Output = T>> Ring for T {}
    impl<T: Ring + Div<T, Output = T>> Field for T {}
}

#[derive(Clone, Eq, PartialEq)]
struct UnionFind<Cost> 
where
    Cost: Copy + algebra::Group + Eq
{
    par: Vec<usize>,
    rank: Vec<usize>,
    pot: Vec<Cost>,
}

impl<Cost> UnionFind<Cost>
where
    Cost: Copy + algebra::Group + Eq + std::fmt::Debug
{
    fn new(n: usize) -> Self {
        UnionFind {
            par : (0..n).collect(),
            rank : vec![0;n],
            pot : vec![Cost::zero(); n],
        }
    }

    fn find(&mut self, x: usize) -> (usize, Cost) {
        if x == self.par[x] {
            (x, Cost::zero())
        } else {
            let par = self.par[x];
            let dis = self.pot[x];
            let (ind, val) = self.find(par);
            self.par[x] = ind;
            self.pot[x] = val+dis;
            (ind, val+dis)
        }
    }

    fn same(&mut self, a: usize, b: usize) -> bool {
        self.find(a) == self.find(b)
    }

    fn unite(&mut self, a: usize, b: usize, c: Cost) -> bool {
        let (apar, apot) = self.find(a);
        let (bpar, bpot) = self.find(b);
        if apar == bpar {
            apot-bpot == c
        } else {
            if self.rank[apar] > self.rank[bpar] {
                self.par[bpar] = apar;
                self.pot[bpar] = apot-bpot-c;
            } else {
                self.par[apar] = bpar;
                self.pot[apar] = c+bpot-apot;
                if self.rank[apar] == self.rank[bpar] {
                    self.rank[bpar] += 1;
                }
            }
            true
        }
    }
}
impl algebra::Zero for i64 {
    fn zero() -> Self { 0 }
}
impl algebra::Zero for i32 {
    fn zero() -> Self { 0 }
}



#[allow(unused_imports)]
use std::cmp::{min, max};
#[allow(unused_imports)]
use std::collections::{BinaryHeap, BTreeMap, HashMap, HashSet};
#[allow(unused_imports)]
use std::collections::btree_map::Entry::{Occupied, Vacant};


fn main() {
    use std::io::Write;
    let out = std::io::stdout();
    let mut out = std::io::BufWriter::new(out.lock());
    macro_rules! printf { ($($arg:tt)*) => (write!(out, $($arg)*).unwrap()); }
    macro_rules! printfln { () => (writeln!(out).unwrap()); ($($arg:tt)*) => (writeln!(out, $($arg)*).unwrap()); }
    let (n, m) = readl!(usize, usize);
    let mut uf = UnionFind::new(n);
    // debug!(uf.par);
    // debug!(uf.pot);
    for _ in 0..m {
        let (l, r, d) = readl!(usize, usize, i32);
        // debug!((l-1, r-1));
        if !uf.unite(l-1, r-1, d) {
            printfln!("No");
            return;
        }
        // debug!(uf.par);
        // debug!(uf.pot);
    }
    printfln!("Yes");
}


Measured memory_bytes: 6396