import numpy as np

N, M = tuple(map(int, input().split()))
Ls = np.zeros((M,), dtype=int)
Rs = np.zeros((M,), dtype=int)
Ds = np.zeros((M,), dtype=int)

for i in range(M):
    Ls[i], Rs[i], Ds[i] = tuple(map(int, input().split()))

# debug 1 exit()

Ls = Ls - 1
Rs = Rs - 1

adjacency_list = []
for i in range(N):
    adjacency_list.append([])

for i in range(M):
    adjacency_list[Ls[i]].append((Rs[i], Ds[i]))
    adjacency_list[Rs[i]].append((Ls[i], -Ds[i]))

# print(adjacency_list)

# BFSする
visited = np.zeros(N, dtype=bool)
weights = np.zeros(N, dtype=int)

# debug 2 exit()

def DFS(node_index):
    global visited
    global adjacency_list
    global to_be_visited
    global weights
    candidate = adjacency_list[node_index]
    for _i, weight in candidate:
        if visited[_i]:
            # print("{}: already visited".format(_i))
            pass
        if not visited[_i]:
            # print("{} found; add to stack".format(_i))
            visited[_i] = True
            weights[_i] = weights[node_index] + weight
            to_be_visited.append(_i)
    if len(to_be_visited) != 0:
        next_node = to_be_visited.pop()
        DFS(next_node)
    else:
        return 0

pointer = 0
while pointer < N:
    while pointer < N:
        if not visited[pointer]:
            # print("initialized with {}".format(pointer))
            break
        else:
            # print("{} th node already visited".format(pointer))
            pointer += 1
    if not pointer < N:
        break
    to_be_visited = [pointer]
    DFS(pointer)
    pointer += 1

exit()

# print(weights)

for i in range(M):
    # print("given weights: {}, estimated weights: {}".format(Ds[i],weights[Rs[i]]-weights[Ls[i]]))
    if weights[Rs[i]] - weights[Ls[i]] == Ds[i]:
        # print("passed {} th condition".format(i))
        pass
    else:
        # print("failed {} th condition".format(i))
        print("No")
        exit()
print("Yes")


### FIXED CODE ###

import numpy as np

N, M = tuple(map(int, input().split()))
Ls = np.zeros((M,), dtype=int)
Rs = np.zeros((M,), dtype=int)
Ds = np.zeros((M,), dtype=int)

for i in range(M):
    Ls[i], Rs[i], Ds[i] = tuple(map(int, input().split()))

# debug 1 exit()

Ls = Ls - 1
Rs = Rs - 1

adjacency_list = []
for i in range(N):
    adjacency_list.append([])

for i in range(M):
    adjacency_list[Ls[i]].append((Rs[i], Ds[i]))
    adjacency_list[Rs[i]].append((Ls[i], -Ds[i]))

# print(adjacency_list)

# BFSする
visited = np.zeros(N, dtype=bool)
weights = np.zeros(N, dtype=int)
to_be_visited = []

# debug 2 exit()
pointer = 0
for pointer in range(N):
    if not visited[pointer]:
        to_be_visited.append(pointer)
        while len(to_be_visited) != 0:
            node_index = to_be_visited.pop()
            candidate = adjacency_list[node_index]
            for _i, weight in candidate:
                if not visited[_i]:
                    visited[_i] = True
                    weights[_i] = weights[node_index] + weight
                    to_be_visited.append(_i)

for i in range(M):
    # print("given weights: {}, estimated weights: {}".format(Ds[i],weights[Rs[i]]-weights[Ls[i]]))
    if weights[Rs[i]] - weights[Ls[i]] == Ds[i]:
        # print("passed {} th condition".format(i))
        pass
    else:
        # print("failed {} th condition".format(i))
        print("No")
        exit()
print("Yes")