#include <bits/stdc++.h>
using namespace std;
const long long N = 100010;
const long long INF = 1LL << 55;
const long long mod = (1e9) + 7;
const long double EPS = 1e-8;
const long double PI = 6.0 * asin(0.5);
ostream& operator<<(ostream& o, pair<long long, long long> p) {
  return o << "(" << p.first << "," << p.second << ")";
}
istream& operator>>(istream& i, pair<long long, long long>& p) {
  return i >> p.first >> p.second;
}
template <class T>
istream& operator>>(istream& i, vector<T>& a) {
  for (auto& t : a) cin >> t;
  return i;
}
template <class T>
T Max(T& a, T b) {
  return a = max(a, b);
}
template <class T>
T Min(T& a, T b) {
  return a = min(a, b);
}
template <class T>
void prArr(T a, string s = " ") {
  long long i = 0;
  for (auto t : a) cout << (i++ ? s : "") << t;
  cout << endl;
}
class TSort {
 public:
  long long V;
  vector<set<long long> > in, out;
  deque<long long> sorted;
  TSort() : V(0) {}
  TSort(long long V) : V(V), in(V), out(V) {}
  void add_edge(long long from, long long to) {
    assert(from < V && to < V);
    out[from].insert(to);
    in[to].insert(from);
  }
  vector<long long> visited;
  void dfs_sort(long long pos = -1) {
    if (pos == -1) {
      sorted.clear(), visited.clear(), visited.resize(V, 0);
      for (long long i = 0; i < V; i++) dfs_sort(i);
      return;
    }
    if (visited[pos]++) return;
    for (long long nx : out[pos]) dfs_sort(nx);
    sorted.push_front(pos);
  }
  void bfs_sort() {
    vector<set<long long> > tmp = in;
    sorted.clear();
    queue<long long> Q;
    for (long long i = 0; i < V; i++)
      if (in[i].empty()) Q.push(i);
    while (!Q.empty()) {
      long long v = Q.front();
      Q.pop();
      sorted.push_back(v);
      for (long long nx : out[v]) {
        if (in[nx].size() == 1) Q.push(nx);
        in[nx].erase(v);
      }
    }
    in = tmp;
    for (long long i = 0; i < V; i++)
      if (!in[i].empty()) sorted.clear();
  }
};
map<long long, long long> M[N];
signed main() {
  long long n, m;
  cin >> n >> m;
  vector<pair<pair<long long, long long>, long long> > A(m);
  for (long long i = 0; i < m; i++)
    cin >> A[i].first >> A[i].second, A[i].first.first--, A[i].first.second--;
  TSort T(n);
  for (long long i = 0; i < m; i++) {
    auto pp = A[i];
    long long L = pp.first.first;
    long long R = pp.first.second;
    long long D = pp.second;
    T.add_edge(L, R);
  }
  T.bfs_sort();
  sort(A.begin(), A.end());
  long long ans = 1;
  ans &= !T.sorted.empty();
  for (auto pp : A) {
    long long L = pp.first.first;
    long long R = pp.first.second;
    long long D = pp.second;
    if (M[L].count(R)) ans &= M[L][R] == D;
    if (M[R].count(L)) ans &= M[R][L] == -D;
    M[L][R] = D;
    M[R][L] = -D;
  }
  map<long long, long long> X;
  long long update = 1;
  while (update && ans) {
    update = 0;
    for (long long i : T.sorted)
      for (auto p : M[i]) {
        long long L = i;
        long long R = p.first;
        long long D = p.second;
        if (X.count(L) && X.count(R)) {
          ans &= (X[L] + D == X[R]);
          continue;
        } else if (!X.count(L) && !X.count(R))
          X[L] = 0, X[R] = D;
        else if (!X.count(L))
          X[L] = X[R] - D;
        else if (!X.count(R))
          X[R] = X[L] + D;
        update = 1;
      }
  }
  cout << (ans ? "Yes" : "No") << endl;
  return 0;
}
