#include <bits/stdc++.h>
using namespace std;
const int inf = (int)1e9;
const long long linf = (long long)1e18;
const int mod = (int)(1e9 + 7);
const int dx[] = {0, 1, 0, -1};
const int dy[] = {1, 0, -1, 0};
const int ddx[] = {0, 1, 1, 1, 0, -1, -1, -1};
const int ddy[] = {1, 1, 0, -1, -1, -1, 0, 1};
const double eps = 1e-10;
struct oreno_initializer {
  oreno_initializer() {
    cin.tie(0);
    ios::sync_with_stdio(0);
  }
} oreno_initializer;
int n, m, l[200000], r[200000], d[200000];
vector<pair<int, int>> e[200000];
int dis[200000];
void dijkstra(int s, vector<pair<int, int>> g[], int *d) {
  priority_queue<pair<int, int>, vector<pair<int, int>>,
                 greater<pair<int, int>>>
      que;
  d[s] = 0;
  que.push(make_pair(0, s));
  while (!que.empty()) {
    pair<int, int> p = que.top();
    que.pop();
    int v = p.second, dis = p.first;
    if (d[v] < dis) continue;
    for (int i = 0; i < g[v].size(); ++i) {
      int to = g[v][i].first, cost = g[v][i].second;
      if (d[to] > d[v] + cost) {
        d[to] = d[v] + cost;
        que.push(make_pair(d[to], to));
      }
    }
  }
}
signed main() {
  cin >> n >> m;
  for (int(i) = 0; (i) < (int)(m); (i)++) {
    cin >> l[i] >> r[i] >> d[i];
    l[i]--, r[i]--;
    e[l[i]].push_back({r[i], d[i]});
    e[r[i]].push_back({l[i], d[i]});
  }
  fill(dis, dis + n, inf);
  for (int(i) = 0; (i) < (int)(n); (i)++)
    if (dis[i] == inf) dijkstra(i, e, dis);
  for (int(i) = 0; (i) < (int)(m); (i)++) {
    if (abs(dis[r[i]] - dis[l[i]]) != d[i]) {
      cout << "NO" << '\n';
      return 0;
    }
  }
  cout << "YES" << '\n';
}
