// Slower C++ solution:
#include<bits/stdc++.h>

using namespace std;

const int MAXN=100007;

typedef long long ll;

struct node {

    int v,w;

    node(int x=0,int y=0) {

        v=x,w=y;

    }

};

int deg[MAXN],X,n,m,x1,x2,y,tot[MAXN];

ll pos[MAXN];

bool vis[MAXN];

char c;

vector<node> edge[MAXN];

inline char nc(){

	static char buf[100000],*p1=buf,*p2=buf;

	return p2==p1&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;

}

int read() {

    X=0,c=nc();

    while(!isdigit(c))c=nc();

    while(isdigit(c))X=(X<<1)+(X<<3)+c-'0',c=nc();

    return X;

}

bool ok;

bool check(int &u) {

    vis[u]=true;

    for(int i=0; i<tot[u]; i++) {

        if(vis[edge[u][i].v]) {

            if(pos[edge[u][i].v]-edge[u][i].w!=pos[u])return false;

        } else {

            pos[edge[u][i].v]=pos[u]+edge[u][i].w;

            if(!check(edge[u][i].v))return false;

            else continue;

        }

    }

    return true;

}

int main() {

        n=read(),m=read();

        if(!m){

            puts("Yes");

            return 0;

        }

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

            x1=read(),x2=read(),y=read();

            tot[x1]++;

            deg[x2]++;

            edge[x1].push_back(node(x2,y));

        }

        for(int i=0; i<n; i++)if(!deg[i]&&tot[i]) {

                ok=1;

                if(!check(i)) {

                    puts("No");

                    return 0;

                }

            };

        if(!ok) {

            puts("No");

            return 0;

        }

        puts("Yes");

        return 0;

}

// Faster C++ solution for the same problem (measured speedup: 3.476474956159882x):
#include<bits/stdc++.h>

using namespace std;



typedef long long lint;

typedef pair<int, int> P;

#define REP(i, x, n) for(lint i = x ; i < n ; i++)

#define rep(i, n) REP(i, 0, n)

#define repr(i, n) for(lint i = n - 1 ; i >= 0 ; i--)

#define SORT(c) sort((c).begin(), (c).end())



const int IINF = 1e9 + 10;

const lint LLINF = (lint)1e18 + 10;

const lint MOD = (lint)1e9 + 7;

const int dx[] = {1, 0, -1, 0}, dy[] = {0, 1, 0, -1};

const int dx8[] = {1, 1, 0, -1, -1, -1, 0, 1}, dy8[] = {0, -1, -1, -1, 0, 1, 1, 1};



struct weightedUnionFind{



    vector<int> par, rank, wei;



    void init(int n){

        par.resize(n);

        rank.resize(n, 0);

        wei.resize(n, 0);

        rep(i, n){

            par[i] = i;

        }

        return;

    }



    int root(int x){

        if(par[x] == x){

            return x;

        }else{

            int r = root(par[x]);

            wei[x] += wei[par[x]];

            return par[x] = r;

        }

    }



    bool unite(int x, int y, int w){

        w = -w;

        w += weight(x);

        w -= weight(y);

        int rx = root(x);

        int ry = root(y);

        if(rx == ry){

            return false;

        }

        if(rank[rx] < rank[ry]){

            swap(rx, ry);

            w = -w;

        }

        if(rank[rx] == rank[ry]){

            rank[rx]++;

        }

        par[ry] = rx;

        wei[ry] = w;

        return true;

    }



    bool same(int x, int y){

        return root(x) == root(y);

    }



    int weight(int x){

        root(x);

        return wei[x];

    }



    int diff(int x, int y){

        return weight(x) - weight(y);

    }



};



int main(){

    int n, m;

    cin >> n >> m;

    weightedUnionFind uf;

    uf.init(n);

    bool flag = true;

    rep(i, m){

        int l, r, d;

        cin >> l >> r >> d;

        l--;

        r--;

        if(uf.same(l, r)){

            if(uf.diff(l, r) != d){

                flag = false;

                break;

            }

        }else{

            uf.unite(l, r, d);

        }

    }

    if(flag){

        cout << "Yes" << endl;

    }else{

        cout << "No" << endl;

    }

    return 0;

}