### BUGGY CODE ###

# -*- coding: utf-8 -*-
from pprint import pprint
import random
from collections import deque, defaultdict
N, M = map(int, input().split())

if M == 0:
    print("Yes")
    exit()

LRD = [list(map(int, input().split())) for _ in range(M)]

# N,M = 100000,200000
# LRD = [[i+10+random.randint(-9,100),i+20+random.randint(-18,200),random.randint(1,300)] for i in range(M)]
# print("run")

# 速めのdfs（非再帰）
graph = defaultdict(lambda: defaultdict(int))
# graph = [[0 for _ in range(N+1)] for _ in range(N+1)]
# graph = [defaultdict(int) for _ in range(N+1)]
visited = defaultdict()

for L,R,D in LRD:
    graph[L][R] = D
    graph[R][L] = -D
    visited[L] = None
    visited[R] = None

# print("step1")
# pprint(graph)

def xfs(v):
    que = deque()
    que.append((v,0))
    while len(que) > 0:
        i,cnt = que.pop()  # 深さ優先探索
        visited[i] = cnt
        # print("step3:i",i)
        for n,val in graph[i].items():
            if visited[n] == None:
                # print("if:v,i,n,cnt,val", v,i,n, cnt, val)
                que.append((n, cnt+val))
            else:
                # print("el:v,i,n,cnt,val,visited[n]",
                #       v, i, n, cnt, val, visited[n])
                if cnt + val != visited[n]:
                    return False

    return True


que2 = deque()
L, _, _ = LRD[0]
que2.append(L)
while len(que2) > 0:
    L = que2.pop()
    # print("step2:L",L)
    if xfs(L):
        for k,v in [(k,v) for k,v in visited.items() if v==None]:
            # print("step4:k", k)
            que2.append(k)
            break
    else:
        # pprint(visited)
        # print("L=",L)
        print("No")
        exit()

# pprint(visited)
print("Yes")


### FIXED CODE ###

# -*- coding: utf-8 -*-
from pprint import pprint
import random
from collections import deque, defaultdict
N, M = map(int, input().split())

if M == 0:
    print("Yes")
    exit()

LRD = [list(map(int, input().split())) for _ in range(M)]

# N,M = 100000,200000
# LRD = [[i+10+random.randint(-9,100),i+20+random.randint(-18,200),random.randint(1,300)] for i in range(M)]
# print("run")

# 速めのdfs（非再帰）
graph = defaultdict(lambda: defaultdict(int))
# graph = [[0 for _ in range(N+1)] for _ in range(N+1)]
# graph = [defaultdict(int) for _ in range(N+1)]
visited = defaultdict()

for L,R,D in LRD:
    graph[L][R] = D
    graph[R][L] = -D
    visited[L] = None
    visited[R] = None

# print("step1")
# pprint(graph)

def xfs(v):
    que = deque()
    que.append((v,0))
    while len(que) > 0:
        i,cnt = que.pop()  # 深さ優先探索
        visited[i] = cnt
        # print("step3:i",i)
        for n,val in graph[i].items():
            if visited[n] == None:
                # print("if:v,i,n,cnt,val", v,i,n, cnt, val)
                que.append((n, cnt+val))
            else:
                # print("el:v,i,n,cnt,val,visited[n]",
                #       v, i, n, cnt, val, visited[n])
                if cnt + val != visited[n]:
                    return False

    return True


que2 = deque()
L, _, _ = LRD[0]
que2.append(L)
while len(que2) > 0:
    L = que2.pop()
    # print("step2:L",L)
    if xfs(L):
        for k,v in [(k,v) for k,v in visited.items() if v==None]:
            # print("step4:k", k)
            que2.append(k)
            break
    else:
        # pprint(visited)
        # print("L=",L)
        print("No")
        exit()

# pprint(visited)
print("Yes")