#include <bits/stdc++.h>
using namespace std;
const double PI = 2 * acos(.0);
const int INF = 0x3f3f3f3f;
const long long LLINF = 1000000000000000005LL;
;
const long long MOD = (long long)(1e9) + 7;
void _mod(long long& x) { x = ((((x) % (MOD)) + (MOD)) % (MOD)); }
const double EPS = 1e-10;
template <typename A, size_t N, typename T>
void Fill(A (&array)[N], const T& val) {
  std::fill((T*)array, (T*)(array + N), val);
}
int pos[101010];
struct UnionFind {
  vector<int> par;
  vector<int> sizes;
  UnionFind(int n) : par(n), sizes(n, 1) {
    for (__typeof(n) i = (0) - ((0) > (n)); i != (n) - ((0) > (n));
         i += 1 - 2 * ((0) > (n)))
      par[i] = i;
  }
  int find(int x) {
    if (x == par[x]) return x;
    return par[x] = find(par[x]);
  }
  void unite(int x, int y, int dis) {
    x = find(x);
    y = find(y);
    if (x == y) return;
    if (sizes[x] < sizes[y]) swap(x, y), dis *= -1;
    par[y] = x;
    for (__typeof(101010) i = 0; i < (101010); i += 1)
      if (find(i) == y) pos[i] += dis;
    sizes[x] += sizes[y];
  }
  bool same(int x, int y) { return find(x) == find(y); }
  int size(int x) { return sizes[find(x)]; }
};
class DPeopleOnALine {
 public:
  int N, M, l, r, d;
  void solve(std::istream& cin, std::ostream& cout) {
    UnionFind uf(101010);
    memset(pos, 0, sizeof(pos));
    cin >> N >> M;
    for (__typeof(M) i = 0; i < (M); i += 1) {
      cin >> l >> r >> d;
      if (uf.find(l) == uf.find(r)) {
        if (pos[r] - pos[l] != d) {
          cout << "No\n";
          return;
        }
      } else {
        uf.unite(l, r, d);
        pos[r] = pos[l] + d;
      }
    }
    cout << "Yes\n";
  }
};
int main() {
  DPeopleOnALine solver;
  std::istream& in(std::cin);
  std::ostream& out(std::cout);
  solver.solve(in, out);
  return 0;
}
