#include <bits/stdc++.h>
using namespace std;
class UnionFind {
  vector<int> data;

 public:
  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 N, M;
vector<vector<int>> f;
map<int, vector<int>> mv;
vector<vector<pair<int, int>>> arc;
bool sub(int rt) {
  int p1 = mv[rt][0];
  set<int> vis;
  vis.insert(p1);
  vector<int> loc(N);
  vector<bool> locset(N, false);
  loc[p1] = 0;
  locset[p1] = true;
  queue<int> q;
  for (auto p : arc[p1]) {
    loc[p.first] = loc[p1] + p.second;
    locset[p.first] = true;
    q.push(p.first);
  }
  while (!q.empty()) {
    int x = q.front();
    q.pop();
    if (((vis).find(x) != (vis).end())) continue;
    for (auto p : arc[x]) {
      if (locset[p.first]) {
        if (loc[p.first] != loc[x] + p.second) return false;
      } else {
        loc[p.first] = loc[x] + p.second;
        locset[p.first] = true;
        if (!((vis).find(p.first) != (vis).end())) q.push(p.first);
      }
    }
  }
  return true;
}
bool solve() {
  arc.resize(N);
  UnionFind uf(N);
  for (int i = 0; i < (M); ++i) {
    int li = f[i][0], ri = f[i][1], di = f[i][2];
    uf.unionSet(li, ri);
    arc[li].push_back(pair<int, int>(ri, di));
    arc[ri].push_back(pair<int, int>(li, -di));
  }
  for (int i = 0; i < (N); ++i) {
    int rt = uf.root(i);
    mv[rt].push_back(i);
  }
  for (auto p : mv) {
    int rt = p.first;
    if (!sub(rt)) return false;
  }
  return true;
}
int main() {
  cin >> N >> M;
  f.resize(M);
  for (int i = 0; i < (M); ++i) {
    int li, ri, di;
    cin >> li >> ri >> di;
    f[i] = {li - 1, ri - 1, di};
  }
  cout << (solve() ? "Yes" : "No") << endl;
  return 0;
}
