#include <bits/stdc++.h>
using namespace std;
struct XX {
  int s;
  int t;
  long long c;
};
class xxGreater {
 public:
  bool operator()(const XX& riLeft, const XX& riRight) const {
    if ((riLeft.s) == (riRight.s)) {
      return riLeft.t < riRight.t;
    }
    return (riLeft.s) < (riRight.s);
  }
};
int ppar[100001];
int rrank[100001];
void init(int n) {
  for (int i = 1; i <= n; i++) {
    ppar[i] = i;
    rrank[i] = 0;
  }
}
int find(int x) {
  if (ppar[x] == x) {
    return x;
  } else {
    return ppar[x] = find(ppar[x]);
  }
}
void unite(int x, int y) {
  x = find(x);
  y = find(y);
  if (x == y) {
    return;
  }
  if (rrank[x] < rrank[y]) {
    ppar[x] = y;
  } else {
    ppar[y] = x;
    if (rrank[x] == rrank[y]) {
      rrank[x]++;
    }
  }
}
bool same(int x, int y) { return find(x) == find(y); }
struct edge {
  int to;
  long long cost;
};
vector<edge> G[100001];
long long depth = 0;
long long depthans = 0;
bool used[100001];
void dfs(int s, int t) {
  used[s] = true;
  if (s == t) {
    depthans = depth;
    return;
  }
  for (int i = 0; i < G[s].size(); i++) {
    if (used[G[s][i].to]) continue;
    depth += G[s][i].cost;
    dfs(G[s][i].to, t);
    depth -= G[s][i].cost;
  }
}
int main(int argc, const char* argv[]) {
  ifstream ifs("a.txt");
  ios::sync_with_stdio(false);
  cin.tie(0);
  int N, M;
  ifs >> N >> M;
  vector<XX> in;
  for (int i = 0; i < M; i++) {
    int tmp, tmp2;
    long long tmp3;
    ifs >> tmp >> tmp2 >> tmp3;
    XX nin;
    nin.s = tmp;
    nin.t = tmp2;
    nin.c = tmp3;
    in.push_back(nin);
  }
  sort(in.begin(), in.end(), xxGreater());
  init(N);
  vector<XX> check;
  int l[200000];
  int r[200000];
  long long d[200000];
  for (int i = 0; i < M; i++) {
    l[i] = in[i].s;
    r[i] = in[i].t;
    d[i] = in[i].c;
    if (same(l[i], r[i])) {
      XX tmp;
      tmp.s = l[i];
      tmp.t = r[i];
    } else {
      unite(l[i], r[i]);
      edge tmp;
      if (r[i] < l[i]) swap(l[i], r[i]);
      tmp.to = r[i];
      tmp.cost = d[i];
      G[l[i]].push_back(tmp);
    }
  }
  for (int i = 0; i < check.size(); i++) {
    fill(used, used + N + 1, false);
    depth = 0;
    depthans = 0;
    dfs(check[i].s, check[i].t);
    if (d[i] != depthans) {
      cout << "No" << endl;
      return 0;
    }
  }
  cout << "Yes" << endl;
  return 0;
}
