// Slower C++ solution:
#include <iostream>

#include <cstdio>

#include <cmath>

#include <vector>

#include <list>

#include <set>

#include <map>

#include <stack>

#include <queue>

#include <string>

#include <utility>

#include <algorithm>

#include <functional>

#include <deque>

#define INF 1e9

#define MAX_M 200001

#define MAX_N 100001



using namespace std;



typedef long long ll;

typedef pair<int,int> P;



struct edge { int to, diff; };



int N, M;

vector<edge> G[MAX_N];

int x[MAX_N];

bool updated[MAX_N];



bool dfs(int i){

    for (int j = 0; j < G[i].size(); ++j) {

        edge e = G[i][j];

        if (!updated[e.to]) {

            x[e.to] = x[i] + e.diff;

            updated[e.to] = true;

            if (!dfs(e.to)) {

                return false;

            }

        } else {

            if (x[e.to] != x[i] + e.diff) {

                return false;

            }

        }

    }

    return true;

}



int main() {

    fill(updated, updated + N, false);

    cin >> N >> M;

    for (int i = 0; i < M; ++i) {

        int l, r, d;

        cin >> l >> r >> d;

        G[l].push_back(edge{r, d});

        G[r].push_back(edge{l, -d});

    }

    

    for (int i = 0; i < N; ++i) {

        if (!updated[i]) {

            x[i] = 0;

            updated[i] = true;

            if (!dfs(i)) {

                cout << "No" << endl;

                return 0;

            }

        }

    }

    

    cout << "Yes" << endl;

    

    return 0;

}


// Faster C++ solution for the same problem (measured speedup: 3.500911142737941x):
#include <cmath>

#include <iostream>

#include <vector>

#include <queue>

#include <deque>

#include <map>

#include <set>

#include <stack>

#include <tuple>

#include <bitset>

#include <algorithm>

#include <functional>

#include <utility>

#include <iomanip>

#define mod(x) ((x % MOD) + MOD) % MOD

#define int long long int

#define rep(i, a, n) for(int i = a; i < n; ++i)

#define rrep(i, a, n) for(int i = n-1; i >= a; --i)



using namespace std;



typedef pair<int,int> P;



const int INF = 1e18;

const int MOD = 1e9+7;



template<typename T> ostream& operator<<(ostream& s, const vector<T>& v) {

  int len = v.size();

  for (int i = 0; i < len; ++i) {

    s << v[i]; if (i < len - 1) s << " ";

  }

  return s;

}



struct edge {

  int to, diff;

};





bool dfs(vector<int>& x, vector< vector<edge> >& G, vector<bool>& used, int i) {

  rep(j, 0, G[i].size()) {

    edge e = G[i][j];

    if (used[e.to]) {

      if (x[i] + e.diff != x[e.to]) {

        return false;

      }

    } else {

      used[e.to] = true;

      x[e.to] = x[i] + e.diff;

      if (!dfs(x, G, used, e.to)) {

        return false;

      }

    }

  }

  return true;

}







signed main()

{

  int N, M;

  cin >> N >> M;

  vector< vector<edge> > G(N, vector<edge>());

  int l, r, d;

  rep(i, 0, M) {

    cin >> l >> r >> d;

    l--; r--;

    G[l].push_back(edge{ r, -d });

    G[r].push_back(edge{ l,  d });

  }



  vector<int> x(N);

  vector<bool> used(N, false);

  rep(i, 0, N) {

    if (!used[i]) {

      x[i] = 0;

      used[i] = true;

      if (!dfs(x, G, used, i)) {

        cout << "No" << endl;

        return 0;

      }

    }

  }



  cout << "Yes" << endl;

  return 0;

}