#include <bits/stdc++.h>
using namespace std;
template <typename T>
string join(vector<T>& v) {
  stringstream s;
  for (int i = (0); i < ((int)(v).size()); i++) s << ' ' << v[i];
  return s.str().substr(1);
}
template <typename A, size_t N, typename T>
void Fill(A (&array)[N], const T& v) {
  fill((T*)array, (T*)(array + N), v);
}
template <typename T>
T gcd(T a, T b) {
  if (a > b) swap(a, b);
  for (; a > 0; b %= a, swap(a, b))
    ;
  return b;
}
long long modpow(__int128_t a, __int128_t n, long long m) {
  if (a == 0) return a;
  __int128_t p = 1;
  for (; n > 0; n /= 2, a = a * a % m)
    if (n & 1) p = p * a % m;
  return (long long)p;
}
void dout(double d) { printf("%.12f\n", d); }
const int iinf = 1e9;
const long long linf = 1e18;
const int mod = 1e9 + 7;
const double pi = acos(-1);
const double eps = 1e-10;
int n, m, l, r;
long long d;
struct UnionFind {
  vector<pair<long long, long long> > p;
  void init(int n) {
    p.resize(n);
    for (int i = (0); i < (n); i++) p[i] = pair<long long, long long>(-1, 0);
  }
  pair<long long, long long> find(int a) {
    if (p[a].first < 0) return pair<long long, long long>(a, 0);
    pair<long long, long long> t = find(p[a].first);
    p[a] = pair<long long, long long>(t.first, t.second + p[a].second);
    return p[a];
  }
  bool merge(int l, int r, long long d) {
    pair<long long, long long> _l = find(l);
    pair<long long, long long> _r = find(r);
    if (_l.first == _r.first) {
      return _r.second - _l.second == d;
    } else {
      p[_r.first] =
          pair<long long, long long>(_l.first, _l.second - _r.second + d);
    }
    return true;
  }
};
UnionFind uf;
int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);
  cin >> n >> m;
  uf.init(n);
  for (int i = (0); i < (m); i++) {
    cin >> l >> r >> d;
    if (!uf.merge(l, r, d)) {
      cout << "No" << endl;
      return 0;
    }
  }
  cout << "Yes" << endl;
  return 0;
}
