#include <bits/stdc++.h>
using namespace std;
using LL = long long;
using VLL = std::vector<LL>;
using VVLL = std::vector<VLL>;
using VVVLL = std::vector<VVLL>;
using LD = long double;
using VLD = std::vector<LD>;
using VVLD = std::vector<VLD>;
using VVVLD = std::vector<VVLD>;
using BL = bool;
using VBL = std::vector<BL>;
using VVBL = std::vector<VBL>;
using VVVBL = std::vector<VVBL>;
template <class T>
inline bool chmax(T &a, T b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}
template <class T>
inline bool chmin(T &a, T b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}
template <class T>
void PRINTSP(vector<T> v, size_t w = 3) {
  for (auto(a) : v) {
    cerr << setw(w) << a << " ";
  }
  cerr << endl;
}
struct mll {
  static LL MOD;
  LL val;
  mll(LL v = 0) : val(v % MOD) {
    if (val < 0) val += MOD;
  }
  mll operator-() const { return -val; }
  mll operator+(const mll &b) const { return val + b.val; }
  mll operator-(const mll &b) const { return val - b.val; }
  mll operator*(const mll &b) const { return val * b.val; }
  mll operator/(const mll &b) const { return mll(*this) /= b; }
  mll operator+(LL b) const { return *this + mll(b); }
  mll operator-(LL b) const { return *this - mll(b); }
  mll operator*(LL b) const { return *this * mll(b); }
  friend mll operator+(LL a, const mll &b) { return b + a; }
  friend mll operator-(LL a, const mll &b) { return -b + a; }
  friend mll operator*(LL a, const mll &b) { return b * a; }
  mll &operator+=(const mll &b) {
    val = (val + b.val) % MOD;
    return *this;
  }
  mll &operator-=(const mll &b) {
    val = (val + MOD - b.val) % MOD;
    return *this;
  }
  mll &operator*=(const mll &b) {
    val = (val * b.val) % MOD;
    return *this;
  }
  mll &operator/=(const mll &b) {
    LL c = b.val, d = MOD, u = 1, v = 0;
    while (d) {
      LL t = c / d;
      c -= t * d;
      swap(c, d);
      u -= t * v;
      swap(u, v);
    }
    val = val * u % MOD;
    if (val < 0) val += MOD;
    return *this;
  }
  mll &operator+=(LL b) { return *this += mll(b); }
  mll &operator-=(LL b) { return *this -= mll(b); }
  mll &operator*=(LL b) { return *this *= mll(b); }
  mll &operator/=(LL b) { return *this /= mll(b); }
  bool operator==(const mll &b) { return val == b.val; }
  bool operator!=(const mll &b) { return val != b.val; }
  bool operator==(LL b) { return *this == mll(b); }
  bool operator!=(LL b) { return *this != mll(b); }
  friend bool operator==(LL a, const mll &b) { return mll(a) == b.val; }
  friend bool operator!=(LL a, const mll &b) { return mll(a) != b.val; }
  friend ostream &operator<<(ostream &os, const mll &a) { return os << a.val; }
  friend istream &operator>>(istream &is, mll &a) { return is >> a.val; }
  static mll Combination(LL a, LL b) {
    chmin(b, a - b);
    if (b < 0) return mll(0);
    mll c = 1;
    for (LL(i) = 0; (i) < (b); (i)++) c *= a - i;
    for (LL(i) = 0; (i) < (b); (i)++) c /= i + 1;
    return c;
  }
  static mll Kumiawase(LL a, LL b) {
    chmin(b, a - b);
    if (b < 0) return mll(0);
    return Junretu(a, b) / Kaijou(b);
  }
  static mll Kaijou(LL a) {
    if (a < 0) return mll(0);
    mll c = 1;
    for (LL i = 1; i <= a; i++) {
      c *= i;
    }
    return c;
  }
  static mll Junretu(LL a, LL b) {
    if (a < b) {
      return mll(0);
    }
    mll c = 1;
    for (LL i = a; i > a - b; i--) {
      c *= i;
    }
    return c;
  }
  static mll _Junretu(LL a, LL b) {
    if (a < b) {
      return mll(0);
    }
    return Kaijou(a) / (Kaijou(a - b));
  }
};
LL mll::MOD = (LL)(1e9 + 7);
using vmll = std::vector<mll>;
using vvmll = std::vector<vmll>;
using vvvmll = std::vector<vvmll>;
using vvvvmll = std::vector<vvvmll>;
template <typename TTT>
vector<LL> arg_sort(vector<TTT> A, bool ascend = true) {
  vector<LL> index(A.size());
  iota(index.begin(), index.end(), 0);
  if (ascend) {
    std::sort(index.begin(), index.end(),
              [&A](TTT i1, TTT i2) { return A[i1] < A[i2]; });
  } else {
    std::sort(index.begin(), index.end(),
              [&A](TTT i1, TTT i2) { return A[i1] > A[i2]; });
  }
  return index;
}
struct UinonFindTree {
 private:
  vector<LL> UFT;

 public:
  UinonFindTree(LL N) {
    UFT.resize(N);
    for (LL i = 0; i < N; i++) {
      UFT[i] = -1;
    }
  }
  LL root(LL i) {
    if (UFT[i] < 0) {
      return i;
    } else {
      LL j = root(UFT[i]);
      UFT[i] = j;
      return j;
    }
  }
  bool same(LL i, LL j) { return (root(i) == root(j)); }
  void unite(LL i, LL j) {
    LL root_i = root(i);
    LL root_j = root(j);
    if (root_i != root_j) {
      if (size(root_i) < size(root_j)) {
        swap(root_i, root_j);
      }
      UFT[root_i] += UFT[root_j];
      UFT[root_j] = root_i;
    }
  }
  LL size(LL i) { return -UFT[root(i)]; }
  LL get_root_num() {
    set<LL> roots;
    for (LL i = 0; i < (LL)UFT.size(); ++i) {
      roots.insert(root(i));
    }
    return (LL)roots.size();
  }
  map<LL, vector<LL>> get_root_child() {
    map<LL, vector<LL>> a;
    for (LL i = 0; i < (LL)UFT.size(); ++i) {
      LL j = root(i);
      a[j].push_back(i);
    }
    return a;
  }
  void print() {
    for (LL i = 0; i < (LL)UFT.size(); ++i) {
      cerr << root(i) << " ";
    }
    cerr << endl;
  }
};
inline VLL cinvll(LL N, LL minus = 0) {
  VLL A(N);
  for (LL(i) = 0; (i) < (N); (i)++) {
    cin >> A[i];
    A[i] -= minus;
  }
  return move(A);
}
inline VVLL zerosll(LL H, LL W, LL val = 0) {
  VVLL A(H, VLL(W, val));
  return move(A);
}
template <typename T>
istream &operator>>(istream &is, vector<T> &vec) {
  for (T &x : vec) is >> x;
  return is;
}
template <typename T, typename U>
ostream &operator<<(ostream &os, pair<T, U> &pair_var) {
  os << "(" << pair_var.first << ", " << pair_var.second << ")";
  return os;
}
template <typename T>
ostream &operator<<(ostream &os, const vector<T> &vec) {
  for (LL i = 0; i < (LL)vec.size(); i++) {
    os << setw(5) << vec[i];
  }
  os << endl;
  return os;
}
template <typename T, typename U>
ostream &operator<<(ostream &os, map<T, U> &map_var) {
  os << "{";
  for (auto itr = map_var.begin(); itr != map_var.end(); itr++) {
    os << *itr;
    itr++;
    if (itr != map_var.end()) os << ", ";
    itr--;
  }
  os << "}";
  return os;
}
template <typename T>
ostream &operator<<(ostream &os, set<T> &set_var) {
  os << "{";
  for (auto itr = set_var.begin(); itr != set_var.end(); itr++) {
    os << *itr;
    itr++;
    if (itr != set_var.end()) os << ", ";
    itr--;
  }
  os << "}";
  return os;
}
void dump_func() { cerr << endl; }
template <class Head, class... Tail>
void dump_func(Head &&head, Tail &&...tail) {
  cerr << ("\033[36m");
  cerr << head;
  if (sizeof...(Tail) > 0) {
    cerr << ", ";
  }
  dump_func(std::move(tail)...);
  cerr << "\033[m";
}
struct Fast {
  Fast() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(std::numeric_limits<double>::max_digits10);
  }
} fast;
void func() {
  LL N, M;
  cin >> N >> M;
  VLL L(N);
  VLL R(N);
  VLL D(N);
  for (LL(i) = 0; (i) < (M); (i)++) {
    cin >> L[i];
    cin >> R[i];
    cin >> D[i];
    L[i]--;
    R[i]--;
  }
  LL INIT_VAL = 1e16;
  VLL A(N, INIT_VAL);
  for (LL(i) = 0; (i) < (M); (i)++) {
    LL l = L[i];
    LL r = R[i];
    LL d = D[i];
    if (A[l] == INIT_VAL and A[r] == INIT_VAL) {
      A[l] = 0;
      A[r] = d + A[l];
    } else if (A[l] == INIT_VAL and A[r] != INIT_VAL) {
      A[l] = d + A[r];
    } else if (A[l] != INIT_VAL and A[r] == INIT_VAL) {
      A[r] = d + A[l];
    } else if (A[l] != INIT_VAL and A[r] != INIT_VAL) {
      if (A[r] != d + A[l]) {
        cout << "No";
        return;
      }
    }
  }
  cout << "Yes";
}
int main() {
  func();
  return 0;
}
