#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = long double;
using pii = pair<int, int>;
using pil = pair<int, ll>;
using pli = pair<ll, int>;
using pll = pair<ll, ll>;
const ll MOD = 1e9 + 7;
const int inf = (1 << 30) - 1;
const ll INF = (1LL << 60) - 1;
const ld EPS = 1e-10;
template <typename T>
bool chmax(T &x, const T &y) {
  return (x < y) ? (x = y, true) : false;
};
template <typename T>
bool chmin(T &x, const T &y) {
  return (x > y) ? (x = y, true) : false;
};
struct Union_Find_Tree {
  vector<int> par, rank, num, p;
  Union_Find_Tree(int N) {
    par.assign(N, -1);
    rank.assign(N, 0);
    num.assign(N, 1);
    p.assign(N, 0);
  }
  int root(int x) {
    if (par[x] < 0 || par[x] == x) return x;
    p[x] += p[par[x]];
    return par[x] = root(par[x]);
  }
  int weight(int x) {
    root(x);
    return p[x];
  }
  bool unite(int x, int y, int w) {
    w += weight(x), w -= weight(y);
    x = root(x), y = root(y);
    if (x == y) return false;
    if (rank[x] < rank[y]) {
      par[x] = y, num[y] += num[x];
      p[x] = -w;
    } else {
      par[y] = x, num[x] += num[y];
      p[y] = w;
      if (rank[x] == rank[y]) rank[x]++;
    }
    return true;
  }
  int size(int x) { return num[root(x)]; }
  bool same(int x, int y) { return root(x) == root(y); }
  void clear() {
    fill(par.begin(), par.end(), -1);
    fill(rank.begin(), rank.end(), 0);
    fill(num.begin(), num.end(), 1);
  }
};
int main() {
  int N, M;
  cin >> N >> M;
  Union_Find_Tree uf(N);
  bool ans = true;
  for (int i = 0; i < M; i++) {
    int u, v, d;
    cin >> u >> v >> d;
    u--, v--;
    if (!uf.unite(u, v, d)) {
      ans &= (uf.weight(v) - uf.weight(u) == d);
    }
  }
  cout << (ans ? "Yes" : "No") << endl;
}
