#include <bits/stdc++.h>
using namespace std;
const long long INF = 1e10;
const double eps = 1e-6;
const long long MOD = 1000000007;
struct UnionFind {
  vector<int> data;
  UnionFind(int size) : data(size, -1) {}
  bool unionSet(int x, int y) {
    x = root(x);
    y = root(y);
    if (x != y) {
      if (data[y] < data[x]) swap(x, y);
      data[x] += data[y];
      data[y] = x;
    }
    return x != y;
  }
  bool findSet(int x, int y) { return root(x) == root(y); }
  int root(int x) { return data[x] < 0 ? x : data[x] = root(data[x]); }
  int size(int x) { return -data[root(x)]; }
};
int main() {
  long long N, M;
  cin >> N >> M;
  UnionFind uf(N);
  vector<vector<tuple<long long, long long, long long>>> q(N);
  for (int i = 0; i < M; i++) {
    long long L, R, D;
    cin >> L >> R >> D;
    L--;
    R--;
    q[L].push_back(tuple<long long, long long, long long>(L, R, D));
    q[R].push_back(tuple<long long, long long, long long>(L, R, D));
    uf.unionSet(L, R);
  }
  vector<int> visited(N, 0);
  set<int> todo;
  vector<long long> iti(N, -1);
  for (int i = 0; i < N; i++) {
    iti[uf.root(i)] = 0;
    todo.insert(uf.root(i));
    visited[uf.root(i)] = true;
  }
  bool ok = true;
  while (!todo.empty()) {
    long long now = *todo.begin();
    todo.erase(todo.begin());
    for (int i = 0; i < q[now].size(); i++) {
      long long l, r, d;
      tie(l, r, d) = q[now][i];
      if (iti[l] == -1)
        iti[l] = iti[r] - d;
      else if (iti[r] == -1)
        iti[r] = iti[l] + d;
      else if (iti[r] - iti[l] != d)
        ok = false;
      if (iti[l] == -1 || iti[r] == -1) cout << "ふえぇ" << endl;
      if (!visited[l]) todo.insert(l);
      if (!visited[r]) todo.insert(r);
      visited[l] = true;
      visited[r] = true;
    }
  }
  if (ok)
    cout << "Yes" << endl;
  else
    cout << "No" << endl;
  return 0;
}
