#include <iostream>
#include <string>
#include <cstdlib>
#include <cstdio>
#include <queue>
#include <stack>
#include <list>
#include <utility>
#include <vector>
#include <set>
#include <algorithm>
#include <cmath>
#include <climits>
#include <map>
#include <unordered_map>
#include <string.h>
#include<iomanip>
#include <iterator>
#include <locale>

#define all(a) a.begin(),a.end()
#define VV(T) vector<vector< T > >
#define rep(i,N) for(int i = 0; i <N; i++)
#define repsg(i,s,g) for(int i = s; i <g; i++)
#define name(x) #x
using namespace std;

const int INF = INT_MAX;
const long long INFL = 1LL<<40;
const double PI = atan(1)*4;
const int MOD = pow(10,9)+7;
int dy[]={0, 0, 1, -1, 0};
int dx[]={1, -1, 0, 0, 0};

typedef long long ll,LL;
typedef vector<int> vint;
typedef vector<vector<int> > vvint;
typedef vector<long long> vll, vLL;
typedef vector<vector<long long> > vvll, vvLL;
typedef pair<int,int> pii;
typedef pair<LL, LL> pLL;


// vector入力
template<typename T>
istream& operator >> (istream& is, vector<T>& vec){
    for(T& x: vec) is >> x;
    return is;
}
// vector出力
template<typename T>
ostream& operator << (ostream& os, vector<T>& vec){
    for(int i=0; i<vec.size(); i++){
        os << vec[i] << ( i+1 == vec.size() ? "" : " " );
    }
    return os;
}
template< typename T >
struct edge{
    int src, to;T cost;
    edge(int to,T cost) :src(-1),to(to),cost(cost){}
    edge(int src, int to, T cost) :src(src),to(to),cost(cost){}edge
    &operator=(const int &x){
        to =x;
        return *this;
    }
    operator int() const{ return to;}
};

template< typename T >
using Edges =vector< edge<T> >;
template< typename T >
using WeightedGraph =vector< Edges<T> >;
using UnWeightedGraph =vector< vector<int> >;
template< typename T >
using Matrix =vector< vector<T> >;


int main() {

    int n,m;cin>>n>>m;
    WeightedGraph<ll> G(n+1);
    
    rep(i,m){
        int l,r; ll d;
        cin>>l>>r>>d;
        G[l].push_back(edge<ll>(l,r,d));
        G[r].push_back(edge<ll>(r,l,-d));
    }
    
    vector<ll> pos(n+1,INFL);
    
    vector<int> checked(n+1,0);
    int cur = 0;
    
    ll bondc = 0;
    
    while(1){
        
        while(cur != n+1 && checked[cur]==1)cur++;
        
        if(cur==n+1)break;
        
        

        int fst = cur;

        queue<int> person;
        person.push(fst);
        person.push(-1);
        pos[fst] = 0;
        checked[fst] = 1;

    
        while(person.size()!=1){
            
            
            
            while(person.front()!=-1){
                
                if(bondc == 2*m) {cout<< "Yes"<<endl; return 0;}
            
                int p = person.front();
                person.pop();
                
                
                for(auto &e:G[p]){
                    
                    if(e.cost == -(1LL<<40)) continue;
                    if(pos[e.to]==INFL) {
                        pos[e.to] = pos[p] + e.cost;
                    }else if (pos[e.to] != pos[p] + e.cost){
                        cout<<"No"<<endl;
                        return 0;
                    }
                    
                    bondc++;
                    
                    
                    person.push(e.to);
                    checked[e.to] =1;
                    e.cost = -(1LL<<40);
                    
                    
                    }
                
            }
            
            person.pop();
            person.push(-1);
            
        }
    }
    
    cout<<"Yes"<<endl;
    
    
    
    return 0;
}










Measured memory_bytes: 14848