#include <bits/stdc++.h>
//#include <atcoder/all>
using namespace std;
//using namespace atcoder;
using ll = long long;
using ld = long double;

#define fi first
#define se second
#define m_p make_pair
#define p_b push_back
#define e_b emplace_back
#define all(x) (x).begin(),(x).end()
#define uniq(x) ((x).erase(unique(all(x)),(x).end()))
#define sz(x) ((int)(x).size())

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

string to_string(string s){
  return '"' + s + '"';
}
string to_string(const char *s){
  return to_string((string)s);
}
string to_string(bool b){
  return (b ? "true" : "false");
}
template<class A, class B>
string to_string(pair<A, B> p){
  return "(" + to_string(p.first) + ", " + to_string(p.second) + ")";
}
template<class A, class B, class C>
string to_string(tuple<A, B, C> p){
  return "(" + to_string(get<0>(p)) + ", " + to_string(get<1>(p)) + ", " + to_string(get<2>(p)) + ")";
}
template<class A, class B, class C, class D>
string to_string(tuple<A, B, C, D> p){
  return "(" + to_string(get<0>(p)) + ", " + to_string(get<1>(p)) + ", " + to_string(get<2>(p)) + ", " + to_string(get<3>(p)) + ")";
}
template<class A>
string to_string(A v){
  bool first = true;
  string res = "{";
  for(const auto &x : v){
    if(!first){
      res += ", ";
    }
    first = false;
    res += to_string(x);
  }
  res += "}";
  return res;
}
void debug_out(){cerr << endl;}
template<class Head, class... Tail>
void debug_out(Head H, Tail... T){
  cerr << " " << to_string(H);
  debug_out(T...);
}
#ifdef LOCAL//compile with -DLOCAL
#define debug(...) cerr << "LINE" << __LINE__ << " [" << #__VA_ARGS__ << "]:", debug_out(__VA_ARGS__)
#else
#define debug(...) void(0)
#endif

template<class T> bool chmax(T &a,T b){if(a<b){a=b;return true;}return false;}
template<class T> bool chmin(T &a,T b){if(a>b){a=b;return true;}return false;}

//トポロジカルソート
vector<int> topological_sort(vector<vector<int>> &graph){
  int N = graph.size();
  vector<int> in_cnt(N);
  for(int i = 0; i < N;i++){
    for(int j = 0; j < (int)graph.at(i).size(); j++){
      in_cnt.at(graph.at(i).at(j))++;
    }
  }

  stack<int> st;
  for(int i = 0; i < N; i++){
    if(in_cnt.at(i) == 0) st.push(i);
  }
  vector<int> ans;
  while(st.size()){
    int v = st.top();
    st.pop();
    ans.p_b(v);
    for(int i = 0; i < (int)graph.at(v).size(); i++){
      int nv = graph.at(v).at(i);
      in_cnt.at(nv)--;
      if(in_cnt.at(nv) == 0)  st.push(nv);
    }
  }
  return ans;
}

vector<ll> dist;
vector<bool> visited;
bool dfs(vector<vector<pair<int,ll>>> &graph, int v){
  if(visited.at(v)) return true;
  visited.at(v) = true;
  if(dist.at(v) == -1e18) dist.at(v) = 0;

  rep(i,sz(graph.at(v))){
    int nv = graph.at(v).at(i).fi;
    int c = graph.at(v).at(i).se;
    if(dist.at(nv) == -1e18){
      dist.at(nv) = dist.at(v) + c;
      if(!dfs(graph, nv)) return false;
    }
    else{
      if(dist.at(nv) != dist.at(v) + c) return false;
    }
  }
  return true;
}

int main(){
  ios_base::sync_with_stdio(false);cin.tie(0);
  int N,M;
  cin >> N >> M;
  vector<int> L(M),R(M),D(M);
  rep(i,M){
    cin >> L.at(i) >> R.at(i) >> D.at(i);
    L.at(i)--;
    R.at(i)--;
  }

  vector<vector<int>> graph_tmp(N);
  rep(i,M){
    graph_tmp.at(L.at(i)).p_b(R.at(i));
  }
  vector<int> t_sort = topological_sort(graph_tmp);
  if(sz(t_sort) != N){
    cout << "No" << endl;
    return 0;
  }

  vector<vector<pair<int,ll>>> graph(N);
  rep(i,M){
    graph.at(L.at(i)).p_b(m_p(R.at(i), D.at(i)));
    graph.at(R.at(i)).p_b(m_p(L.at(i), -D.at(i)));
  }
  dist.resize(N);
  visited.resize(N);
  rep(i,N){
    dist.at(i) = -1e18;
    visited.at(i) = false;
  }
  rep(i,N){
    if(!dfs(graph,i)){
      cout << "No" << endl;
      return 0;
    }
  }
  cout << "Yes" << endl;

  return 0;
}

Measured memory_bytes: 27992