#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;

struct Edge{
    int to, cost;
    bool used = false;
};
vector<Edge> vec[100010];
constexpr int INF = 1 << 29;

int main(){
    int N, M;
    cin >> N >> M;

    vector<int64_t> cntL(N);
    vector<int64_t> cntR(N);
    for(int i = 0; i < M; ++i){
        int L, R, D;
        cin >> L >> R >> D;
        --L, --R;
        vec[L].push_back(Edge{R, D});
        //vec[R].push_back(Edge{L, -D});
        cntL[L]++;
        cntR[R]++;
    }
    queue<int> que;
    for(int i = 0; i < N; ++i){
        if(cntL[i] > 0 && cntR[i] == 0){
            que.push(i);
        }
    }
    if(M == 0){
        cout << "Yes" << endl;
        return 0;
    }
    if(que.empty()){
        cout << "No" << endl;
        return 0;
    }
    
    vector<int64_t> d(N);
    for(int i = 0; i < N; ++i){
        d[i] = INF;
    }
    d[que.front()] = 0;

    bool check = true;
    while(!que.empty()){
        int q = que.front();
        que.pop();
        for(auto c : vec[q]){
            if(!c.used){
                if(d[c.to] == INF && d[q] != INF){
                    d[c.to] = d[q] + c.cost;
                    que.push(c.to);
                }
                else if(d[q] != INF && d[c.to] != d[q] + c.cost){
                    check = false;
                    break;
                }
                else {
                    d[q] = d[c.to] - c.cost;
                }
                c.used = true;
            }
        }
    }
    cout << (check ? "Yes" : "No") << endl;
}