// Original C++ solution (slower):
#include <iostream>

#include <cstring>

#include <algorithm>

#include <vector>

#include <string>

#include <math.h>

#include <stdio.h>

#include <iomanip>

#include <limits>

#include <list>

#include <queue>

#include <deque>

#include <tuple>

#include <map>

#include <sstream>

using namespace std;

#define MOD (long long int)(1e9+7)

#define ll long long int

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

#define reps(i,n) for(int i=1; i<=(int)(n); i++)

#define REP(i,n) for(int i=n-1; i>=0; i--)

#define REPS(i,n) for(int i=n; i>0; i--)

#define FOR(i,a,b) for(int i=a; i<(int)(b); i++)

#define ALL(x) (x).begin(),(x).end()

#define RALL(a) (a).rbegin(), (a).rend()

#define SORT(c) sort(ALL(x))

#define CLR(a) memset((a), 0 ,sizeof(a))

#define PB push_back

#define MP make_pair

#define SP << " " <<

const int INF = 1001001001;

const ll LINF = 100100100100100100;

const double EPS = 1e-10;

const double PI  = acos(-1.0);

typedef pair<int,int> PII;

typedef vector<int> VI;

typedef vector<VI> VVI;



template<typename A, size_t N, typename T>

void Fill(A (&array)[N], const T &val){

    std::fill( (T*)array, (T*)(array+N), val );

}

__attribute__((constructor))

void initial(){

	cin.tie(nullptr);

	ios::sync_with_stdio(false);

	cout << fixed << setprecision(15);

}





const int lim = 100100;

int n,m;

vector<PII> G[lim];

bool visited[lim];

int x[lim];



bool dfs(int p){

  visited[p] = true;

  for(auto &t : G[p]){

    if(visited[t.first]){

      if(x[t.first] != x[p]+t.second) return false;

      continue;

    }else{

      x[t.first] = x[p]+t.second;

      if(!dfs(t.first)) return false;

    }

  }

  return true;

}



signed main(){

  cin>>n>>m;

  rep(i,m){

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

    G[l].PB({r,d}); G[r].PB({l,-d});

  }

  reps(i,n){

    if(visited[i]) continue;

    if(!dfs(i)){

      cout << "No" << endl;

      return 0;

    }

  }

  cout << "Yes" << endl;

  return 0;

}


// Optimized solution to the same problem (faster):
#include <iostream>

#include <cstring>

#include <algorithm>

#include <vector>

#include <string>

#include <math.h>

#include <stdio.h>

#include <iomanip>

#include <limits>

#include <list>

#include <queue>

#include <deque>

#include <tuple>

#include <map>

#include <sstream>

using namespace std;

#define MOD (long long int)(1e9+7)

#define ll long long int

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

#define reps(i,n) for(int i=1; i<=(int)(n); i++)

#define REP(i,n) for(int i=n-1; i>=0; i--)

#define REPS(i,n) for(int i=n; i>0; i--)

#define FOR(i,a,b) for(int i=a; i<(int)(b); i++)

#define ALL(x) (x).begin(),(x).end()

#define RALL(a) (a).rbegin(), (a).rend()

#define SORT(c) sort(ALL(x))

#define CLR(a) memset((a), 0 ,sizeof(a))

#define PB push_back

#define MP make_pair

#define SP << " " <<

const int INF = 1001001001;

const ll LINF = 100100100100100100;

const double EPS = 1e-10;

const double PI  = acos(-1.0);

typedef pair<int,int> PII;

typedef vector<int> VI;

typedef vector<VI> VVI;



template<typename A, size_t N, typename T>

void Fill(A (&array)[N], const T &val){

    std::fill( (T*)array, (T*)(array+N), val );

}

__attribute__((constructor))

void initial(){

	cin.tie(nullptr);

	ios::sync_with_stdio(false);

	cout << fixed << setprecision(15);

}





template<class Abel> struct UnionFind{

    VI par, rank;

    vector<Abel> diff_weight;

    UnionFind(int n=1, Abel SUM_UNITY=0){

        init(n, SUM_UNITY);

    }

    void init(int n=1, Abel SUM_UNITY=0){

        par.resize(n); rank.resize(n); diff_weight.resize(n);

        rep(i,n) par[i] = i, rank[i] = 0, diff_weight[i] = SUM_UNITY;

    }

    int root(int x){

        if(par[x]==x) return x;

        int r = root(par[x]);

        diff_weight[x] += diff_weight[par[x]];

        return par[x] = r;

    }

    Abel weight(int x){

        root(x);

        return diff_weight[x];

    }

    bool issame(int x, int y){

        return root(x)==root(y);

    }

    bool merge(int x, int y, Abel w){

        w += weight(x); w -= weight(y);

        x = root(x); y = root(y);

        if(x==y) return false;

        if(rank[x]<rank[y]) swap(x, y), w = -w;

        if(rank[x]==rank[y]) rank[x]++;

        par[y] = x;

        diff_weight[y] = w;

        return true;

    }

    Abel diff(int x, int y){

        return weight(y)-weight(x);

    }

};



int main() {

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

    UnionFind<int> uf(n);

    rep(i,m){

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

        if(uf.issame(l,r)){

            int diff=uf.diff(l,r);

            if(diff!=d){

                cout << "No" << endl;

                return 0;

            }

        }

        else{

            uf.merge(l,r,d);

        }

    }

    cout << "Yes" << endl;

    return 0;

}


// Fastest known solution for this problem: