// Slower C++ solution:
#include <bits/stdc++.h>

//---------------------------

using namespace std;

//---------------------------

#define REP(i,n) for(int i = 0; i < (n); i++)

#define P(x) cout << (x) << "\n"

#define fcout cout << fixed << setprecision(18)



#define MOD 1000000007 // 1e9+7

#define PI 3.1415926535

/*

3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679

*/

#define ll long long int // 10^18

#define INF 1000000001 // 1e9+1

#define LINF 1000000000000000001 // 1e18+1



int dx[4]={1,-1,0,0};

int dy[4]={0,0,1,-1};

//---------------------------

//

const int N=1e+5, M=2e+5;



vector<pair<ll,ll>> G[N];



bool ok=true;

bool visited[N];

int weights[N];



void dfs(int v){

  visited[v]=true;

  REP(i,(int)G[v].size()){

    int to=G[v][i].first;

    int weight=G[v][i].second;

    // cout<<v<<" "<<to<<" "<<weight<<"\n";

    // cout<<visited[to]<<"\n";

    if(!visited[to]){

      weights[to]=weights[v] + weight;

      // cout<<weights[to]<<" "<<weights[v]<<"\n";

      dfs(to);

    }else{

      if(weights[to] != weights[v]+weight){

        // cout<<weights[to]<<" "<<weights[v]<<"\n";

        ok=false;

      }

    }

  }

}



int main(){

  std::ios::sync_with_stdio(false);

  std::cin.tie(0);



  // ifstream in("input.txt");

  // cin.rdbuf(in.rdbuf());



  int n,m;cin>>n>>m;

  REP(i,m){

    int a,b,d;cin>>a>>b>>d;

    --a;--b;

    G[a].push_back(make_pair(b,d));

    G[b].push_back(make_pair(a,-d));

  }



  REP(i,n){

    if(!visited[i]){

      dfs(i);

    }

  }

  if(ok){

    P("Yes");

  }else{

    P("No");

  }

  return 0;

}


// Faster C++ solution for the same problem (measured speedup: 3.510589099048833x):
// PotentializedUnionFindTree

#include <bits/stdc++.h>

//---------------------------

using namespace std;

//---------------------------

#define REP(i,n) for(int i = 0; i < (n); i++)

#define P(x) cout << (x) << "\n"

#define fcout cout << fixed << setprecision(18)



#define MOD 1000000007 // 1e9+7

#define PI 3.1415926535

/*

3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679

*/

#define ll long long int // 10^18

#define INF 1000000001 // 1e9+1

#define LINF 1000000000000000001 // 1e18+1



int dx[4]={1,-1,0,0};

int dy[4]={0,0,1,-1};

//---------------------------



template <class Abelian> class PotentializedUnionFind {



public:

  using value_type = Abelian;

  using size_type = size_t;

  using container_type =

      vector<tuple<size_type, value_type, size_type>>;



protected:

  container_type c;



private:

  size_type &par(const size_type i) { return get<0>(c[i]); }

  value_type &val(const size_type i) { return get<1>(c[i]); }

  size_type &siz(const size_type i) { return get<2>(c[i]); }

  value_type potential(size_type x) {

    value_type ret = {};

    while (x != par(x)) {

      val(x) = val(x) + val(par(x));

      ret = ret + val(x);

      x = par(x) = par(par(x));

    }

    return std::move(ret);

  }



public:

  PotentializedUnionFind() : c() {}

  explicit PotentializedUnionFind(const size_type size)

      : c(size, forward_as_tuple(static_cast<size_type>(0), value_type(),

                                      static_cast<size_type>(1))) {

    for (size_type i = 0; i < size; ++i)

      par(i) = i;

  }



  size_type size() const { return c.size(); }

  bool empty() const { return c.empty(); }



  size_type find(size_type x) {

    assert(x < size());

    while (x != par(x)) {

      val(x) = val(x) + val(par(x));

      x = par(x) = par(par(x));

    }

    return x;

  }

  value_type diff(const size_type x, const size_type y) {

    assert(x < size());

    assert(y < size());

    assert(same(x, y));

    return potential(y) + (-potential(x));

  }

  bool same(const size_type x, const size_type y) {

    assert(x < size());

    assert(y < size());

    return find(x) == find(y);

  }

  size_type size(const size_type x) {

    assert(x < size());

    return siz(find(x));

  }



  bool unite(size_type x, size_type y, value_type d) {

    assert(x < size());

    assert(y < size());

    d = d + potential(x) + (-potential(y));

    x = find(x);

    y = find(y);

    if (x == y)

      return false;

    if (siz(x) < siz(y))

      swap(x, y), d = -d;

    siz(x) += siz(y);

    par(y) = x;

    val(y) = move(d);

    return true;

  }

};



int main(){

  std::ios::sync_with_stdio(false);

  std::cin.tie(0);



  // ifstream in("input.txt");

  // cin.rdbuf(in.rdbuf());



  int n,m;cin>>n>>m;

  PotentializedUnionFind<int> PUF(n);

  REP(i,m){

    int l,r,d;cin>>l>>r>>d;

    l--;r--;

    if(!PUF.unite(l,r,d)){

      if(PUF.diff(l,r) != d){

        P("No");

        return 0;

      }

    }

  }

  P("Yes");

  return 0;

}