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

#define FOR(i,a,b) for(int i=(a);i<(b);++i)

#define REP(i,n)  for(int i=0;i<(n);++i)

#define FORq(i, m, n) for(int i = (m);i <= (n);++i)

#define SCD(n) scanf("%d",&n)

#define SCD2(m,n) scanf("%d%d",&m,&n)

#define SCD3(m,n,k) scanf("%d%d%d",&m,&n,&k)

#define SCLLD(n) scanf("%lld",&n)

#define SCLLD2(m,n) scanf("%lld%lld",&m,&n)

#define SCLLD3(m,n,k) scanf("%lld%lld%lld",&m,&n,&k)

#define PB push_back

#define MP make_pair

#define ARSCD(A,N) REP(i,N){SCD(A[i]);}

#define ARSCD1(A,N) FORq(i,1,N){SCD(A[i]);}

#define PRINTD(n) printf("%d\n",n)

#define PRINTLLD(n) printf("%lld\n",n)

#define DEBUG printf("%s\n","debug")

#define fst first

#define snd second

#define SIN(x,S) (S.count(x) != 0)

using namespace std;

typedef pair<int,int> PII;

typedef vector<int> VI;

typedef vector < VI > VVI;

typedef long long ll;

typedef long long integer;

//////////////////////////////////////////////////

struct Vertex {

	// edge information

	vector<int> edges_to; //to vertex number

	vector<integer> edges_cost; // edge cost

	

	//for dijkstra

	bool done; //conform or not

	integer cost; // now cost

	int from;

	

	bool operator<(const Vertex& another) const { // priority --> min

        return another.cost < cost; // order(cost)

    }

	

	bool operator==(const Vertex& another) const {

        return another.cost == cost; // order(cost)

    }

};



Vertex V[100002];



int main(){

    int N,M;

    SCD2(N,M);



    REP(i,M){

        int L,R;

        integer D;

        SCD2(L,R);

        SCLLD(D);

        

/*         if (L>R){

            swap(L,R);

            D = -D;

        } */



        V[L].edges_to.PB(R);

        V[L].edges_cost.PB(D);

        V[R].edges_to.PB(L);

        V[R].edges_cost.PB(-D);

    }



    bool ans = true;





    FORq(s,1,N){

        if (V[s].done) continue;

        queue<int> Q;

        Q.push(s);

        V[s].cost = 0;

        V[s].done = true;



        int nowpos = s;

        integer nowcost = 0;

        while(!Q.empty()){

            nowpos = Q.front();

            nowcost = V[nowpos].cost;

            Q.pop();



            REP(i,V[nowpos].edges_to.size()){

                int nextpos = V[nowpos].edges_to[i];

                integer nextcost = V[nowpos].edges_cost[i];



                if ((V[nextpos].done) and (nowcost + nextcost != V[nextpos].cost)){

                    printf("No\n");

                    return 0;

                }else if(!V[nextpos].done){

                    Q.push(nextpos);

                }

                

                V[nextpos].done = true;

                V[nextpos].cost = nowcost + nextcost;

            }

        }

    }



    printf("Yes\n");





}


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

#define FOR(i,a,b) for(int i=(a);i<(b);++i)

#define REP(i,n)  for(int i=0;i<(n);++i)

#define FORq(i, m, n) for(int i = (m);i <= (n);++i)

#define SCD(n) scanf("%d",&n)

#define SCD2(m,n) scanf("%d%d",&m,&n)

#define SCD3(m,n,k) scanf("%d%d%d",&m,&n,&k)

#define SCLLD(n) scanf("%lld",&n)

#define SCLLD2(m,n) scanf("%lld%lld",&m,&n)

#define SCLLD3(m,n,k) scanf("%lld%lld%lld",&m,&n,&k)

#define PB push_back

#define MP make_pair

#define ARSCD(A,N) REP(i,N){SCD(A[i]);}

#define ARSCD1(A,N) FORq(i,1,N){SCD(A[i]);}

#define PRINTD(n) printf("%d\n",n)

#define PRINTLLD(n) printf("%lld\n",n)

#define DEBUG printf("%s\n","debug")

#define fst first

#define snd second

#define SIN(x,S) (S.count(x) != 0)

using namespace std;

typedef pair<int,int> PII;

typedef vector<int> VI;

typedef vector < VI > VVI;

typedef long long ll;

typedef long long integer;

//////////////////////////////////////////////////

// Union-Find with potential

//https://qiita.com/drken/items/cce6fc5c579051e64fab



struct Potential_UnionFind {

    vector<int> par;

    vector<long long> diff_weight;

    Potential_UnionFind(int n = 1, long long SUM_UNITY = 0) {

        init(n, SUM_UNITY);

    }



    void init(int n = 1, long long SUM_UNITY = 0) {

        par.resize(n); diff_weight.resize(n);

        for (int i = 0; i < n; ++i) par[i] = -1, diff_weight[i] = SUM_UNITY;

    }



    int root(int x){

        if (par[x] < 0) {

            return x;

        }else{

            //path compression

            int rt = root(par[x]);

            diff_weight[x] += diff_weight[par[x]];

            return par[x] = root(par[x]);

        }

    }



    int size(int x){

        return -par[root(x)];

    }



    int weight(int x){

        root(x);

        return diff_weight[x];

    }



    int diff(int x,int y){

        return weight(y) - weight(x);

    }



    bool isConnect(int x,int y){

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

    }



    bool connect(int x , int y, long long w){

        //weight(y) - weight(x) = w

        //xとyの差を無理やりwにするために現状の親からのpotentialの差をキャンセルする．

        w += weight(x); w-= weight(y);

        x = root(x);

	    y = root(y);

	

        if(x==y) return false;

        

        //if rank[x] < rank[y]

        if(par[x] > par[y]){

            x ^= y;

            y ^= x;

            x ^= y;

            w = -w;

        }

        

        par[x] = par[x] + par[y]; // membersize++

        par[y] = x;

        diff_weight[y] = w;

        return true;

    }

};



Potential_UnionFind U(100002);



int main(){

    int N,M;

    SCD2(N,M);



    REP(i,M){

        int L,R;

        integer D;

        SCD2(L,R); SCLLD(D);



        if (U.isConnect(L,R)){

            if (D != (integer)U.diff(L,R)){

                printf("No\n");

                return 0;

            }

        }else{

            U.connect(L,R,D);

        }

    }



    printf("Yes\n");

}