// Original C++ solution (slower):
#include <iostream>

#include <vector>

#include <algorithm>

#include <cmath>

#include <queue>

#include <string>

#include <map>

#include <set>

#include <stack>

#include <tuple>

#include <deque>

#include <numeric>

#include <bitset>

#include <iomanip>

#include <cassert>

#include <chrono>

#include <random>

#include <limits>

#include <iterator>

#include <functional>

#include <sstream>

#include <complex>

using namespace std;



typedef long long ll;

typedef uint64_t ull;

typedef pair<int, int> P;

typedef pair<int, double> Pid;

typedef pair<double, int> Pdi;

typedef pair<ll, int> Pl;

typedef pair<ll, ll> Pll;

typedef pair<int, pair<int, int>> PP;

typedef pair<P, int> PPi;

constexpr double PI = 3.1415926535897932;   // acos(-1)

constexpr double EPS = 1e-9;

constexpr int INF = 1001001001;

constexpr int mod = 1000000007;

// constexpr int mod = 998244353;



#define chmax(x, y) x = max(x, y)

#define chmin(x, y) x = min(x, y)

#define chadd(x, y) x = (x + y) % mod



vector<P> graph[100005];

vector<ll> dist(100005, 1e+15);

bool setted[100005];



bool dfs(int from){

    for(auto p : graph[from]){

        int to = p.first, cost = p.second;

        if(setted[to]){

            if(dist[to] != dist[from] + cost)   return false;

        }

        else{

            setted[to] = true;

            dist[to] = dist[from] + cost;

            if(!dfs(to))    return false;

        }

    }

    return true;

}



int main(){

    ios::sync_with_stdio(false);

    cin.tie(nullptr);



    int n, m;

    cin >> n >> m;

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

        int l, r, d;

        cin >> l >> r >> d;

        --l, --r;

        graph[l].push_back(P(r, d));

        graph[r].push_back(P(l, -d));

    }

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

        if(!setted[i]){

            setted[i] = true;

            dist[i] = 0;

            if(!dfs(i)){

                cout << "No\n";

                return 0;

            }

        }

    }

    cout << "Yes\n";

}

// Optimized solution to the same problem (faster):
#include <iostream>

#include <vector>

#include <algorithm>

#include <cmath>

#include <queue>

#include <string>

#include <map>

#include <set>

#include <stack>

#include <tuple>

#include <deque>

#include <numeric>

#include <bitset>

#include <iomanip>

#include <cassert>

#include <chrono>

#include <random>

#include <limits>

#include <iterator>

#include <functional>

#include <sstream>

#include <complex>

using namespace std;



using ll = long long;

using ull = uint64_t;

using P = pair<int, int>;

constexpr double EPS = 1e-9;

constexpr int INF = 1001001001;

// constexpr int mod = 1000000007;

constexpr int mod = 998244353;



template<class T>

inline bool chmax(T& x, T y){

    if(x < y){

        x = y;

        return true;

    }

    return false;

}

template<class T>

inline bool chmin(T& x, T y){

    if(x > y){

        x = y;

        return true;

    }

    return false;

}



int main(){

    ios::sync_with_stdio(false);

    cin.tie(nullptr);



    int n, m;

    cin >> n >> m;

    vector<vector<P>> graph(n);

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

        int l, r, d;

        cin >> l >> r >> d;

        --l, --r;

        graph[l].emplace_back(r, d);

        graph[r].emplace_back(l, -d);

    }

    vector<int> x(n, INF);

    auto dfs = [&](auto&& self, int from) -> bool {

        for(auto e : graph[from]){

            int to = e.first, cost = e.second;

            if(x[to] != INF){

                if(x[to] != x[from] + cost) return false;

            }

            else{

                x[to] = x[from] + cost;

                if(!self(self, to)) return false;

            }

        }

        return true;

    };

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

        if(x[i] == INF){

            x[i] = 0;

            if(!dfs(dfs, i)){

                cout << "No\n";

                return 0;

            }

        }

    }

    cout << "Yes\n";

}

// Fastest known solution for this problem: