#include <bits/stdc++.h>
using namespace std;
const long long LLINF = (1LL << 60);
const long long INF = (1LL << 30);
const long long MOD = 1000000007;
class UnionFind {
 public:
  UnionFind(long long size) { m_Data.assign(size, -1); }
  bool Unite(long long x, long long y) {
    x = Find(x), y = Find(y);
    if (x == y) {
      return (false);
    }
    if (m_Data[x] > m_Data[y]) {
      swap(x, y);
    }
    m_Data[x] += m_Data[y];
    m_Data[y] = x;
    return (true);
  }
  long long Find(long long k) {
    if (m_Data[k] < 0) {
      return (k);
    }
    return (m_Data[k] = Find(m_Data[k]));
  }
  long long Size(long long k) { return (-m_Data[Find(k)]); }

 private:
  vector<long long> m_Data;
};
template <typename T,
          typename enable_if<is_integral<T>::value, nullptr_t>::type = nullptr>
class BellmanFord {
 private:
  struct Edge {
    T from;
    T to;
    T cost;
  };

 public:
  BellmanFord(T v, T inf) : m_V(v), m_Inf(inf) { m_D = new T[m_V]; }
  ~BellmanFord() { delete[] m_D; }
  void AddDirEdge(T from, T to, T cost) { m_Es.push_back({from, to, cost}); }
  void AddUndirEdge(T from, T to, T cost) {
    AddDirEdge(from, to, cost);
    AddDirEdge(to, from, cost);
  }
  void Calc(T s) {
    for (long long i = 0; i < m_V; ++i) {
      m_D[i] = m_Inf;
    }
    m_D[s] = 0;
    while (true) {
      bool update = false;
      for (auto& e : m_Es) {
        if (m_D[e.from] != m_Inf && m_D[e.to] > m_D[e.from] + e.cost) {
          m_D[e.to] = m_D[e.from] + e.cost;
          update = true;
        }
      }
      if (!update) {
        break;
      }
    }
  }
  T GetDist(T t) { return m_D[t]; }
  bool FindNegativeLoop() {
    memset(m_D, 0, sizeof(m_D));
    for (long long i = 0; i < m_V; ++i) {
      for (auto& e : m_Es) {
        if (m_D[e.to] > m_D[e.from] + e.cost) {
          m_D[e.to] = m_D[e.from] + e.cost;
          if (i == m_V - 1) {
            return true;
          }
        }
      }
    }
    return false;
  }

 private:
  const T m_V;
  const T m_Inf;
  T* m_D;
  vector<Edge> m_Es;
};
long long N, M;
vector<pair<pair<long long, long long>, long long> > Lrd;
vector<pair<pair<long long, long long>, long long> > group[100010];
set<long long> exist;
bool check(vector<pair<pair<long long, long long>, long long> >& v,
           long long root) {
  BellmanFord<long long> bf(N, LLINF);
  for (auto& edge : v) {
    long long l = edge.first.first;
    long long r = edge.first.second;
    long long d = edge.second;
    bf.AddDirEdge(l, r, d);
    bf.AddDirEdge(r, l, -d);
  }
  if (bf.FindNegativeLoop()) {
    return false;
  }
  return true;
}
signed main() {
  cin >> N >> M;
  UnionFind uf(N);
  for (long long i = 0; i < M; ++i) {
    long long l, r, d;
    cin >> l >> r >> d;
    l--;
    r--;
    Lrd.push_back({{l, r}, d});
    uf.Unite(l, r);
  }
  for (long long i = 0; i < M; ++i) {
    long long id = uf.Find(Lrd[i].first.first);
    group[id].push_back(Lrd[i]);
    exist.insert(id);
  }
  for (auto& id : exist) {
    if (!check(group[id], id)) {
      printf("No\n");
      return 0;
    }
  }
  printf("Yes\n");
  return 0;
}
