#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <fstream>
#include <sstream>
#include <set>
#include <map>
#include <vector>
#include <list>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <string>
#include <queue>
#include <bitset>     //UWAGA - w czasie kompilacji musi byc znany rozmiar wektora - nie mozna go zmienic
#include <cassert>
#include <iomanip>        //do setprecision
#include <ctime>
#include <complex>
using namespace std;

#define FOR(i,b,e) for(int i=(b);i<(e);++i)
#define FORQ(i,b,e) for(int i=(b);i<=(e);++i)
#define FORD(i,b,e) for(int i=(b)-1;i>=(e);--i)
#define REP(x, n) for(int x = 0; x < (n); ++x)

#define FORT(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();++i)
#define ALL(c) (c).begin(), (c).end()


#define ST first
#define ND second
#define PB push_back
#define MP make_pair
#define LL long long
#define ULL unsigned LL
#define LD long double

const double pi = 3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342;
const int mod=1000000007;

vector<int> i2g;          // i2g[i] := アイテム i の所属するグループの番号(find)
vector<vector<int>> g2i;  // g2i[g] := グループ g に所属するアイテムたち

void union_init(int n) {
  i2g.resize(n);
  g2i.resize(n);
  for (int i = 0; i < n; ++i) {
    // 最初はアイテム i はグループ i に所属
    i2g[i] = i;
    g2i[i].assign(1, i);
  }
}

int find(int i){
  return i2g[i];
}

// アイテム ia の所属するグループとアイテム ib の所属するグループを 1 つにする
void merge(int ia, int ib) {
  if(i2g[ia]==i2g[ib])return;
  // ia の所属するグループが ib の所属するグループより小さくならないようにする
  if (g2i[i2g[ia]].size() < g2i[i2g[ib]].size()) {
    swap(ia, ib);
  }
  int ga = i2g[ia], gb = i2g[ib];
  // グループ gb に所属する全てのアイテムをグループ ga に移す
  for (int j : g2i[gb]) i2g[j] = ga;
  g2i[ga].insert(g2i[ga].end(), g2i[gb].begin(), g2i[gb].end());
  g2i[gb].clear();
}

// アイテム ia とアイテム ib は同じグループに所属しているか？
bool is_same_group(int ia, int ib) {
  return i2g[ia] == i2g[ib];
}


struct edge
{
	edge(int t,int c){
		to=t;
		cost=c;
	}
	edge(){}
  int to, cost;
};

int main(){
	int n,m,l,r,d;
	vector< vector<edge> > g;
	g.reserve(101010);
	int b[101010]={};

	cin>>n>>m;
	union_init(n+1);
	FORQ(i,0,n){
		b[i]=-1;
	}
	FOR(i,0,m){
		cin>>l>>r>>d;
		edge ee;
		ee.to=r;
		ee.cost=d;
		g[l].emplace_back(r,d);
		ee.to=l;
		ee.cost=-d;
		g[r].push_back(ee);
		merge(l,r);
	}

	FORQ(i,1,n){
		if(b[i]==-1)b[i]=mod;
		else continue;
		queue<int>  q;
		for(auto itr = g[i].begin()-g[i].begin(); itr != g[i].end()-g[i].begin(); ++itr) {
        if(b[g[i][itr].to]!=-1&&b[g[i][itr].to]!=b[i]+g[i][itr].cost){
					//cout<<i<<" "<<itr<<" from:"<<i<<" to:"<<g[i][itr].to<<" cost:"<<g[i][itr].cost<<endl;
					cout<<"No"<<endl;
					return 0;
				}
				q.push(g[i][itr].to);
				b[g[i][itr].to]=b[i]+g[i][itr].cost;
    }
		while(!q.empty()){
			int t=q.front();
			q.pop();
			for(auto itr = g[t].begin()-g[t].begin(); itr != g[t].end()-g[t].begin(); ++itr) {
	        if(b[g[t][itr].to]!=-1&&b[g[t][itr].to]!=b[t]+g[t][itr].cost){
						//cout<<i<<" "<<itr<<" from:"<<i<<" to:"<<g[i][itr].to<<" cost:"<<g[i][itr].cost<<endl;
						cout<<"No"<<endl;
						return 0;
					}
					if(b[g[t][itr].to]==-1)q.push(g[t][itr].to);
					b[g[t][itr].to]=b[t]+g[t][itr].cost;
	    }
		}
	}
	cout<<"Yes"<<endl;
    return 0;
}


Measured memory_bytes: 16256