################
class UnionFind():
    """
    parents : 親要素(findしない場合は根ではないことの注意)，根の場合は"-(要素数）"
    find(x):要素xの属するグループの根を返す
    size(x):要素xの属するグループの要素数を返す
    same(x,y):x,yが同じグループに属しているか返す
    members(x):要素xが属するグループに属する要素をリストで返す
    roots:全ての根の要素を返す
    group_count():グループの数を返す
    all_group_members():{根要素：[そのグループに含まれる要素のリスト]}の辞書を返す
    """
    def __init__(self, n):
        self.n = n
        self.parents = [-1] * n

    def find(self, x):
        if self.parents[x] < 0:
            return x
        else:
            self.parents[x] = self.find(self.parents[x])
            return self.parents[x]

    def union(self, x, y):
        x = self.find(x)
        y = self.find(y)

        if x == y:
            return

        if self.parents[x] > self.parents[y]:
            x, y = y, x

        self.parents[x] += self.parents[y]
        self.parents[y] = x

    def size(self, x):
        return -self.parents[self.find(x)]

    def same(self, x, y):
        return self.find(x) == self.find(y)

    def members(self, x):
        root = self.find(x)
        return [i for i in range(self.n) if self.find(i) == root]

    def roots(self):
        return [i for i, x in enumerate(self.parents) if x < 0]

    def group_count(self):
        return len(self.roots())

    def all_group_members(self):
        return {r: self.members(r) for r in self.roots()}

    def __str__(self):
        return '\n'.join('{}: {}'.format(r, self.members(r)) for r in self.roots())
    
################

from collections import defaultdict

N,M=map(int,input().split())
uf = UnionFind(N)
L=[0]*N
R=[0]*N
D=[0]*N
x=[-1]*N

f=1

for i in range(M):
    L[i],R[i],D[i]=map(int,input().split())
    L[i]-=1
    R[i]-=1
    uf.union(L[i],R[i])
    if x[L[i]]==-1 and x[R[i]]==-1:
        x[L[i]]=0
        x[R[i]]=D[i]
    elif x[L[i]]==-1:
        x[L[i]]=x[R[i]]-D[i]
    elif x[R[i]]==-1:
        x[R[i]]=x[L[i]]+D[i]
    else:
        if x[R[i]]-x[L[i]]!=D[i]:
            f=0
    
#範囲の判定

cnt_g=uf.group_count()
Max = defaultdict(int)
Min  = defaultdict(int)


for i in range(N):
    gi=uf.find(i)
    xx=x[i]
    Max[gi]=max(Max[gi],xx)
    Min[gi]=min(Min[gi],xx)
    
inf=10**9    


roots=uf.roots()

for i in roots:
    l=Max[i]-Min[i]
    if l>inf:
        f=0
    
    
            
            
            
if f==1:
    print("Yes")
else:
    print("No")
        
    





### FIXED CODE ###

import sys
input = sys.stdin.readline


N,M=map(int,input().split())
adj=[[] for _ in range(N)]
inf = 10**9+1
x=[inf]*N

L=[0]*M
R=[0]*M
D=[0]*M
fro=[0]*N#何個入ってくる？

for i in range(M):
    L[i],R[i],D[i]=map(int,input().split())
    L[i]-=1
    R[i]-=1
    adj[L[i]].append([R[i],D[i]])
    fro[R[i]]+=1
    #adj[R[i]].append([L[i],-1*D[i]])
    
    
roots=[]
for i in range(N):
    if fro[i]==0:
        roots.append(i)

queue=[]
#距離の設定
for root in roots:
    if x[root]==inf:
        queue.append([root,-1])#node,pare
        x[root]=0
        while queue:
            node,par=queue.pop()
            num=len(adj[node])
            for i in range(num):
                to,cost=adj[node][i]
                if x[to]==inf:#見たことがなければ
                    x[to]=x[node]+cost
                    queue.append([to,node])
            
    
f=1
#判定
for i in range(M):
    d=x[R[i]]-x[L[i]]
    if d!=D[i]:
        f=0
            
    
    
            
            
            
if f==1:
    print("Yes")
else:
    print("No")