#include <bits/stdc++.h>
#define fst first
#define snd second
#define rep(n) for(lint I = 0; (I) < (lint)(n); ++(I))
#define repeat(i, n) for(lint i = 0; (i) < (lint)(n); ++(i))
#define repeat_to(i, n) for(lint i = 0; (i) <= (lint)(n); ++(i))
#define repeat_from(i, m, n) for(lint i = (m); (i) < (lint)(n); ++(i))
#define repeat_from_to(i, m, n) for(lint i = (m); (i) <= (lint)(n); ++(i))
#define repeat_reverse_from_to(i, m, n) for(lint i = (m); (i) >= (lint)(n); --(i))
#define el cout<<endl
#define dump(x) cout<<" "<<#x<<"="<<x
#define vdump(v) for(size_t I=0; I<v.size(); ++I){cout<<" "<<#v<<"["<<I<<"]="<<v[I];} cout<<endl
using namespace std;
using lint = long long;
using ld = long double;

/****************** グラフ ******************/
// 諸宣言
using Weight = lint;
using Flow = lint;
struct Edge {
    int src, dst;
    Weight weight;
    Flow cap;
    Edge() : src(0), dst(0), weight(0) {}
    Edge(int s, int d, Weight w) : src(s), dst(d), weight(w) {}
    Edge(int s, int d, Weight w, Flow c) : src(s), dst(d), weight(w), cap(c) {}
};
using Edges = vector<Edge>;
using Graph = vector<Edges>;
using Array = vector<Weight>;
using Matrix = vector<Array>;

void add_edge(Graph &g, int a, int b, Weight w = 1, Flow c = 1) {
    g[a].emplace_back(a, b, w, c);
    g[b].emplace_back(b, a, w, c);
}
void add_arc(Graph &g, int a, int b, Weight w = 1, Flow c = 1) {
    g[a].emplace_back(a, b, w, c);
}

int main(void) {
    
    int n, m; cin >> n >> m;
    Graph g(n);
    map<tuple<int, int>, int> mp;
    
    repeat (i, m) {
        int src, dst, wgt;
        cin >> src >> dst >> wgt;
        add_arc(g, src-1, dst-1, wgt);
        add_arc(g, dst-1, src-1, (-1)*wgt);
        
        tuple<int, int> ta(src-1, dst-1), tb(dst-1, src-1);
        mp[ta] = wgt; mp[tb] = (-1)*wgt;
    }
    
    
    vector<bool> visit(n, false);
    vector<int>  value(n, -1);
    
    auto getdis = [&](int src, int dst) -> int {
        /*for (const auto &v : g[src]) {
            if (v.dst == dst) {
                return v.weight;
            }
        }*/
        tuple<int, int> t(src, dst);
        return mp[t];
    };
    
    auto dfs = [&](pair<int, int> p) -> void {
        stack<pair<int, int>> s;
        visit[p.snd] = true;
        s.push(p);
        while (not s.empty()) {
            pair<int, int> q = s.top();
            s.pop();
            int src = q.fst;
            int dst = q.snd;
            if (src == -1) {
                value[dst] = 0;
            }
            else {
                value[dst] = value[src] + getdis(src, dst);
            }
            //dump(src); dump(dst); if(src != -1){ dump(getdis(g, src, dst));} vdump(value); vdump(visit); el;
            for (const auto& i : g[dst]) {
                if (not visit[i.dst]) {
                    visit[i.dst] = true;
                    s.push(pair<int,int> (dst, i.dst));
                    //dump(dst); dump(i.dst); el;
                }
            }
        }
    };
    
    /*
    auto unvisited = [](vector<bool>& visit) -> int {
        for (int i = 0; i < (int)visit.size(); ++i) {
            if (visit[i]) continue;
            else return i;
        }
        return -1;
    };
    */
    
    repeat (v, n) {
        if (visit[v]) continue;
        pair<int, int> p (-1, v);
        //dump(p.fst); dump(p.snd); el;
        dfs(p);
    }
    
    for (const auto &v : g) {
        for (const auto &e : v) {
            int src = e.src;
            int dst = e.dst;
            int wgt = e.weight;
            if (value[dst] - value[src] != wgt) {
                cout << "No" << endl;
                return 0;
            }
        }
    }
    cout << "Yes" << endl;
    return 0;
    
}

Measured memory_bytes: 42112