CodeEff/ECCO huggingface dataset:
# Original solution
import sys
input = sys.stdin.readline
n, m = list(map(int, input().split()))
q = [list(map(int, input().split())) for i in range(m)]

g = [[] for i in range(n+1)]

for i in range(m):
    a, b, c = q[i]
    g[a].append((b, c))
    g[b].append((a, -c))

people = [-10**10] * (n+1)

flag = 1
for i in range(1, n+1):
    if people[i] != -10**10:
        continue
    q = [i]
    while q:
        now = q.pop()
        for next, dist in g[now]:
            if people[next] == -10**10:
                q.append(next)
                people[next] = people[now] + dist
            else:
                if people[next] == people[now] + dist:
                    continue
                else:
                    flag = 0
                    break
        if flag == 0:
            break

if max(people[1:]) - min(people[1:]) > 10**9:
    flag = 0
    
if flag == 1:
    print("Yes")
else:
    print("No")


# Optimized solution
import sys
input = sys.stdin.readline
n, m = list(map(int, input().split()))
q = [list(map(int, input().split())) for i in range(m)]

g = [[] for i in range(n+1)]

for i in range(m):
    a, b, c = q[i]
    g[a].append((b, c))
    g[b].append((a, -c))

people = [-10**10] * (n+1)

flag = 1
for i in range(1, n+1):
    if people[i] != -10**10:
        continue
    q = [i]
    people[i] = 0
    while q:
        now = q.pop()
        for next, dist in g[now]:
            if people[next] == -10**10:
                q.append(next)
                people[next] = people[now] + dist
            else:
                if people[next] == people[now] + dist:
                    continue
                else:
                    flag = 0
                    break
        if flag == 0:
            break

if max(people[1:]) - min(people[1:]) > 10**9:
    flag = 0

if flag == 1:
    print("Yes")
else:
    print("No")
# Original solution
class WeightedUnionFind:
    def __init__(self, n):
        self.parent = [i for i in range(n + 1)]
        self.rank = [0 for _ in range(n + 1)]
        self.weight = [0 for _ in range(n + 1)]

    def find(self, x):
        if self.parent[x] == x:
            return x
        else:
            y = self.find(self.parent[x])
            self.weight[x] += self.weight[self.parent[x]]
            self.parent[x] = y
            return y

    def union(self, x, y, w):
        rx = self.find(x)
        ry = self.find(y)
        if rx == ry:
            if w != self.diff(x, y):
                print("No")
                exit()

        if self.rank[rx] < self.rank[ry]:
            self.parent[rx] = ry
            self.weight[rx] = w - self.weight[x] + self.weight[y]
        else:
            self.parent[ry] = rx
            self.weight[ry] = -w - self.weight[y] + self.weight[x]
            if self.rank[rx] == self.rank[ry]:
                self.rank[rx] += 1

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

    def diff(self, x, y):
        return self.weight[x] - self.weight[y]


N, M = list(map(int, input().split()))
w_union_find = WeightedUnionFind(N)
for i in range(M):
    l, r, d = list(map(int, input().split()))
    w_union_find.union(l, r, d)
print("Yes")


# Optimized solution
class WeightedUnionFind:
    def __init__(self, n):
        self.parent = [i for i in range(n + 1)]
        self.rank = [0 for _ in range(n + 1)]
        self.weight = [0 for _ in range(n + 1)]

    def find(self, x):
        if self.parent[x] == x:
            return x
        else:
            y = self.find(self.parent[x])
            self.weight[x] += self.weight[self.parent[x]]
            self.parent[x] = y
            return y

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

        if self.rank[rx] < self.rank[ry]:
            self.parent[rx] = ry
            self.weight[rx] = w - self.weight[x] + self.weight[y]
        else:
            self.parent[ry] = rx
            self.weight[ry] = -w - self.weight[y] + self.weight[x]
            if self.rank[rx] == self.rank[ry]:
                self.rank[rx] += 1

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

    def diff(self, x, y):
        return self.weight[x] - self.weight[y]


N, M = list(map(int, input().split()))
items = []
for i in range(M):
    items.append(tuple(map(int, input().split())))

wu = WeightedUnionFind(N)

for i in range(M):
    l, r, d = items[i]
    if wu.same(l, r):
        if d == wu.diff(l, r):
            continue
        else:
            print("No")
            exit()
    else:
        wu.union(l, r, d)

print("Yes")
# Original solution
import sys
sys.setrecursionlimit(300000)

N, M = list(map(int, input().split()))

nl = [[] for _ in range(N + 1)]
for _ in range(M):
    L, R, D = list(map(int, input().split()))
    nl[L].append((R, D))
    nl[R].append((L, -D))

# print(nl)
    
seen = [None for _ in range(N + 1)]

def dfs(v, d):
    # print("dfs ", v, d)
    seen[v] = d
    for next_v, D in nl[v]:
        next_d = d + D
        if seen[next_v] is None:
            dfs(next_v, next_d)
        else:
            if seen[next_v] != next_d:
                print('No')
                exit(0)
                
for v in range(1, N + 1):  # すべての連結成分に対してDFS
    if seen[v] is None:
        dfs(v, 0)

print('Yes')

# Optimized solution
N,M = list(map(int,input().split()))
LRD = [list(map(int,input().split())) for _ in [0]*M]

E = [{} for _ in [0]*N]
for L,R,D in LRD:
    E[L-1][R-1] = D
    E[R-1][L-1] = -D

V = [None]*N
breakFlg = False
for i in range(N):
    if V[i]!=None:
      	continue
    V[i] = 0
    q = [i]
    while q:
        j = q.pop()
        v = V[j]
        for k,d in list(E[j].items()):
            if V[k] == None:
                V[k] = v+d
                q.append(k)
ans = True
for l,e in enumerate(E):
    for r,d in list(e.items()):
        ans = ans and V[r]-V[l]==d
    if not ans:
      	break
print(("Yes" if ans else "No"))
# Original solution
n, m = list(map(int, input().split()))
vertices = {i: [] for i in range(n)}
for _ in range(m):
    l, r, d = list(map(int, input().split()))
    vertices[l - 1].append((r - 1, d))
    vertices[r - 1].append((l - 1, -d))


def answer():
    x = [None] * n

    while any(i is None for i in x):
        i = x.index(None)
        x[i] = 0
        queue = [i]

        while queue:
            i0 = queue.pop()
            for i1, d in vertices[i0]:
                # print(i0, i1, x[i0], x[i1], d)
                if x[i1] is None:
                    x[i1] = x[i0] + d
                    queue.append(i1)
                elif x[i1] != x[i0] + d:
                    return False

    return True


if answer():
    print('Yes')
else:
    print('No')





# Optimized solution
n, m = list(map(int, input().split()))
vertices = {i: [] for i in range(n)}
for _ in range(m):
    l, r, d = list(map(int, input().split()))
    vertices[l - 1].append((r - 1, d))
    vertices[r - 1].append((l - 1, -d))


def answer():
    x = [None] * n

    for i in range(n):
        if x[i] is not None:
            continue
        x[i] = 0
        queue = [i]

        while queue:
            i0 = queue.pop()
            for i1, d in vertices[i0]:
                # print(i0, i1, x[i0], x[i1], d)
                if x[i1] is None:
                    x[i1] = x[i0] + d
                    queue.append(i1)
                elif x[i1] != x[i0] + d:
                    return False

    return True


if answer():
    print('Yes')
else:
    print('No')
# Original solution
import sys
sys.setrecursionlimit(2147483647)
INF=float("inf")
MOD=10**9+7
input=lambda :sys.stdin.readline().rstrip()
def resolve():
    n,m=list(map(int,input().split()))
    E=[[] for _ in range(n)]
    for _ in range(m):
        u,v,w=list(map(int,input().split()))
        u-=1; v-=1
        E[v].append((u,w))
    # dfsで各連結成分毎に最長経路を計算していく
    # 仮に更新されるようなことがあれば矛盾
    dist=[INF]*n
    visited=[0]*n
    def dfs(v)->bool:
        d=0
        flag=False
        visited[v]=1
        for nv,w in E[v]:
            # ループ検出
            if(visited[nv] and dist[nv]==INF):
                return False
            # nv の最長経路を計算
            if(not dfs(nv)):
                return False
            else:
                if(not flag):
                    d=dist[nv]+w
                    flag=True
                else:
                    if(d!=dist[nv]+w):
                        return False
        dist[v]=d
        return True
    print(("Yes" if(all(dfs(v) for v in range(n))) else "No"))
resolve()

# Optimized solution
import sys
sys.setrecursionlimit(2147483647)
INF=float("inf")
MOD=10**9+7
input=lambda :sys.stdin.readline().rstrip()
def resolve():
    n,m=list(map(int,input().split()))
    E=[[] for _ in range(n)]
    for _ in range(m):
        u,v,w=list(map(int,input().split()))
        u-=1; v-=1
        E[u].append((v,w))
        E[v].append((u,-w))

    pos=[INF]*n # position
    def dfs(v)->bool:
        if(pos[v]!=INF): return True
        pos[v]=0
        Q=[v]
        while(Q):
            v=Q.pop()
            for nv,w in E[v]:
                if(pos[nv]==INF):
                    pos[nv]=pos[v]+w
                    Q.append(nv)
                else:
                    if(pos[nv]!=pos[v]+w):
                        return False
        return True
    for v in range(n):
        if(not dfs(v)):
            print("No")
            return
    print("Yes")
resolve()
# Original solution
import queue
n,m = list(map(int,input().split()))

data =[0]
access = [False]*(n+1)
dis = [0]+[" "]*(n)
q = queue.Queue()
for i in range(n):
    data.append([])

for i in range(m):
    l,r,d = list(map(int,input().split()))

    data[l].append((r,d))
    data[r].append((l,-d))

for i in range(1,n+1):
    data[i].sort(reverse=True)

for i in range(1,n+1):
    if data[i]!=[] and not access[i]: 
        q.put(i)
        access[i] = True
        dis[i] = 0
        while not q.empty():
            l = q.get()

            for r,d in data[l]:
                if access[r]:
                    if dis[r] ==dis[l]+d:
                        continue
                    else:
                        print("No")
                        exit(0)
                else:
                    access[r] = True
                    dis[r] = dis[l]+d
                    q.put(r)
print("Yes")


# Optimized solution
import queue
n,m = list(map(int,input().split()))

data =[0]
access = [False]*(n+1)
dis = [0]+[" "]*(n)
q = queue.Queue()
for i in range(n):
    data.append([])

for i in range(m):
    l,r,d = list(map(int,input().split()))

    data[l].append((r,d))
    data[r].append((l,-d))

for i in range(1,n+1):
    data[i].sort(reverse=True)

for i in range(1,n+1):
    if data[i]!=[] and not access[i]: 
        q.put(i)
        access[i] = True
        dis[i] = 0
        while not q.empty():
            l = q.get()

            while data[l]:
                r,d = data[l].pop()
                if access[r]:
                    if dis[r] ==dis[l]+d:
                        continue
                    else:
                        print("No")
                        exit(0)
                else:
                    access[r] = True
                    dis[r] = dis[l]+d
                    q.put(r)
print("Yes")
# Original solution
import queue
n,m = list(map(int,input().split()))

data =[0]
access = [False]*(n+1)
dis = [0]+[" "]*(n)
q = queue.Queue()
for i in range(n):
    data.append([])

for i in range(m):
    l,r,d = list(map(int,input().split()))

    data[l].append((r,d))
    data[r].append((l,-d))

for i in range(1,n+1):
    data[i].sort(reverse=True)

for i in range(1,n+1):
    if data[i]!=[] and not access[i]: 
        q.put(i)
        access[i] = True
        dis[i] = 0
        while not q.empty():
            l = q.get()

            while data[l]:
                r,d = data[l].pop()
                if access[r]:
                    if dis[r] ==dis[l]+d:
                        continue
                    else:
                        print("No")
                        exit(0)
                else:
                    access[r] = True
                    dis[r] = dis[l]+d
                    q.put(r)
print("Yes")


# Optimized solution
import queue
n,m = list(map(int,input().split()))

data =[0]
access = [False]*(n+1)
dis = [0]+[" "]*(n)
q = queue.Queue()
for i in range(n):
    data.append([])

for i in range(m):
    l,r,d = list(map(int,input().split()))

    data[l].append((r,d))
    data[r].append((l,-d))

for i in range(1,n+1):
    data[i].sort(reverse=True)

for i in range(1,n+1):
    if data[i]!=[] and not access[i]: 
        q.put(i)
        access[i] = True
        dis[i] = 0
        while not q.empty():
            l = q.get()

            while data[l]:
                r,d = data[l].pop()
                data[r].remove((l,-d))
                if access[r]:
                    if dis[r] ==dis[l]+d:
                        continue
                    else:
                        print("No")
                        exit(0)
                else:
                    access[r] = True
                    dis[r] = dis[l]+d
                    q.put(r)
print("Yes")
# Original solution
n, m = list(map(int, input().split()))
par = list(range(n+1))
dis = [0] * (n+1)

def root(x):
  if x == par[x]:
    return x
  r = root(par[x])
  dis[x] += dis[par[x]]
  par[x] = r
  return r

def cost(x):
  # xからxの根までのコスト
  if x == par[x]:
    return 0
  return dis[x] + cost(par[x])

# 確かめ用
def unite(x, y, w):
  rootx = root(x)
  rooty = root(y)
  if rootx != rooty:
    if y != rooty:
      # 直接yにつなげる
      dis[rootx] = w - cost(x)
    else:
      # 根につなげる
      dis[rootx] = w - (dis[x] - dis[y])
    # ここで親を更新
    par[rootx] = y
  else:
    if w != cost(x) - cost(y):
      print("No")
      exit()


for _ in range(m):
  l, r, d = list(map(int, input().split()))
  # 根が違ってればマージ
  # 同じなら入力されたdistanceがこれまでの入力データからなる
  # 現在の木の構造から計算した数値とあっているか判断
  rootl, rootr = root(l), root(r)
  # 確かめ用
  a = unite(l, r, d)
  if a is not None:
    if a == False:
      flag = False

  """
  ちょっとなにがダメなのかわかんないので確かめる
  if rootl != rootr:
    # lをrにマージする
    if r == rootr:
      dis[rootl] = d - cost(l)
    else:
      dis[rootl] = d - (dis[l] - dis[r]) # (cost(l) - cost(r))
    par[rootl] = r
  else:
    # コストが同じかどうか
    if d == cost(l) - cost(r):
      continue
    else:
      print("No")
      exit()
  """
print("Yes")

# Optimized solution
n, m = list(map(int, input().split()))
par = list(range(n+1))
dis = [0] * (n+1)

def root(x):
  if x == par[x]:
    return x
  r = root(par[x])
  dis[x] += dis[par[x]]
  par[x] = r
  return r

def cost(x):
  # xからxの根までのコスト
  if x == par[x]:
    return 0
  return dis[x] + cost(par[x])

for _ in range(m):
  l, r, d = list(map(int, input().split()))
  # 根が違ってればマージ
  # 同じなら入力されたdistanceがこれまでの入力データからなる
  # 現在の木の構造から計算した数値とあっているか判断
  # rootl, rootr = root(l), root(r)
  # 確かめ用
  rootl = root(l)
  rootr = root(r)
  if rootl != rootr:
    if r != rootr:
      # 直接yにつなげる
      dis[rootl] = d - cost(l)
    else:
      # 根につなげる
      dis[rootl] = d - (dis[l] - dis[r])
    # ここで親を更新
    par[rootl] = r
  else:
    if d != cost(l) - cost(r):
      print("No")
      exit()

  """
  ちょっとなにがダメなのかわかんないので確かめる
  if rootl != rootr:
    # lをrにマージする
    if r == rootr:
      dis[rootl] = d - cost(l)
    else:
      dis[rootl] = d - (dis[l] - dis[r]) # (cost(l) - cost(r))
    par[rootl] = r
  else:
    # コストが同じかどうか
    if d == cost(l) - cost(r):
      continue
    else:
      print("No")
      exit()
  """
print("Yes")
# Original solution
n, m = list(map(int, input().split()))
par = list(range(n+1))
dis = [0] * (n+1)

def root(x):
  if x == par[x]:
    return x
  r = root(par[x])
  dis[x] += dis[par[x]]
  par[x] = r
  return r

def cost(x):
  # xからxの根までのコスト
  if x == par[x]:
    return 0
  return dis[x] + cost(par[x])

for _ in range(m):
  l, r, d = list(map(int, input().split()))
  # 根が違ってればマージ
  # 同じなら入力されたdistanceがこれまでの入力データからなる
  # 現在の木の構造から計算した数値とあっているか判断
  # rootl, rootr = root(l), root(r)
  # 確かめ用
  rootl = root(l)
  rootr = root(r)
  if rootl != rootr:
    if r != rootr:
      # 直接yにつなげる
      dis[rootl] = d - cost(l)
    else:
      # 根につなげる
      dis[rootl] = d - (dis[l] - dis[r])
    # ここで親を更新
    par[rootl] = r
  else:
    if d != cost(l) - cost(r):
      print("No")
      exit()

  """
  ちょっとなにがダメなのかわかんないので確かめる
  if rootl != rootr:
    # lをrにマージする
    if r == rootr:
      dis[rootl] = d - cost(l)
    else:
      dis[rootl] = d - (dis[l] - dis[r]) # (cost(l) - cost(r))
    par[rootl] = r
  else:
    # コストが同じかどうか
    if d == cost(l) - cost(r):
      continue
    else:
      print("No")
      exit()
  """
print("Yes")

# Optimized solution
n, m = list(map(int, input().split()))
par = list(range(n+1))
dis = [0] * (n+1)

def root(x):
  if x == par[x]:
    return x
  r = root(par[x])
  dis[x] += dis[par[x]]
  par[x] = r
  return r

def cost(x):
  # xからxの根までのコスト
  if x == par[x]:
    return 0
  return dis[x] + cost(par[x])

for _ in range(m):
  l, r, d = list(map(int, input().split()))
  # 根が違ってればマージ
  # 同じなら入力されたdistanceがこれまでの入力データからなる
  # 現在の木の構造から計算した数値とあっているか判断
  # rootl, rootr = root(l), root(r)
  # 確かめ用
  rootl = root(l)
  rootr = root(r)
  if rootl != rootr:
    if r != rootr:
      # 直接yにつなげる
      dis[rootl] = d - cost(l)
    else:
      # 根につなげる
      dis[rootl] = d - (cost(l) - cost(r)) # (dis[l] - dis[r])
    # ここで親を更新
    par[rootl] = r
  else:
    if d != cost(l) - cost(r):
      print("No")
      exit()

  """
  ちょっとなにがダメなのかわかんないので確かめる
  if rootl != rootr:
    # lをrにマージする
    if r == rootr:
      dis[rootl] = d - cost(l)
    else:
      dis[rootl] = d - (dis[l] - dis[r]) # (cost(l) - cost(r))
    par[rootl] = r
  else:
    # コストが同じかどうか
    if d == cost(l) - cost(r):
      continue
    else:
      print("No")
      exit()
  """
print("Yes")
# Original solution
from collections import defaultdict
g = defaultdict(list)

n, m = list(map(int, input().split()))
if m==0:
    print('Yes')
    exit()
for i in range(m):
    l, r, d = list(map(int, input().split()))
    g[l].append((r, d))
    g[r].append((l, -1*d))
    
visited = {}
vv = {k:None for k in list(g.keys())}
def dfs(v):
    stack = []
    visited[v] = True
    stack.append((v,0))
    while len(stack)!= 0:
        v,w = stack.pop()
        vv[v] = w
        for c,d in g[v]:
            if not visited.get(c, False):
                visited[c] = True
                stack.append((c,w+d))

f = list(g.keys())[0]
not_visited = list(g.keys())
while True:
    dfs(f)
    not_visited = list(set(not_visited) - set(visited.keys()))
    if not_visited == []: break
    else: f = not_visited[0]

for k in list(g.keys()):
    v = vv[k]
    for c,w in g[k]:
        if not v + w == vv[c]:
            print('No')
            exit()

print('Yes')

# Optimized solution
from collections import defaultdict
g = defaultdict(list)

n, m = list(map(int, input().split()))
if m==0:
    print('Yes')
    exit()
for i in range(m):
    l, r, d = list(map(int, input().split()))
    g[l].append((r, d))
    g[r].append((l, -1*d))
    
visited = {}
vv = {k:None for k in list(g.keys())}
def dfs(v):
    stack = []
    visited[v] = True
    stack.append((v,0))
    while len(stack)!=0:
        v,w = stack.pop()
        vv[v] = w
        for c,d in g[v]:
            if not visited.get(c, False):
                visited[c] = True
                stack.append((c,w+d))

for f in list(g.keys()):
    if not visited.get(f):
        dfs(f)

for k in list(g.keys()):
    v = vv[k]
    for c,w in g[k]:
        if not v + w == vv[c]:
            print('No')
            exit()

print('Yes')
# Original solution
n,m = map(int, input().split())
ml = [[-1 for i in range(n)] for j in range(n)]

for i in range(m):
    l,r,d = map(int, input().split())
    l -= 1
    r -= 1
    if ml[l][l] == -1 and ml[r][r] == -1:
        ml[l][l] = 0
        ml[r][r] = d
    elif ml[l][l] != -1 and ml[r][r] == -1:
        ml[r][r] = d + ml[l][l]
    elif ml[l][l] == -1 and ml[r][r] != -1:
        ml[l][l] = ml[r][r] - d
    else:
        if ml[r][r] - ml[l][l] != d:
            print('No', flush=True)
            import sys
            sys.exit()

print('Yes', flush=True)


# Optimized solution
import sys
n,m = list(map(int, input().split()))

# it watches only end of union
# for i in range(m):
#     l,r,d = map(int, input().split())
#     if ml[l] == -1 and ml[r] == -1:
#         ml[l] = 0
#         ml[r] = d
#     elif ml[l] != -1 and ml[r] == -1:
#         ml[r] = d + ml[l]
#         if ml[r] > n:
#             print('R', i, ml[l], ml[r], flush=True)
#             print('No', flush=True)
#             sys.exit()
#     elif ml[l] == -1 and ml[r] != -1:
#         ml[l] = ml[r] - d
#         if ml[l] < 1:
#             print('L', i, ml[l], ml[r], flush=True)
#             print('No', flush=True)
#             sys.exit()
#     else:
#         if ml[r] - ml[l] != d:
#             print('B', i, l, ml[l], r, ml[r], d, flush=True)
#             print('No', flush=True)
#             sys.exit()
# print('Yes', flush=True)

class UnionfindWithWeight():
    def __init__(self,n):
        self.parents=[-1]*n
        self.ranks=[0]*n
        self.dist=[0]*n
    def find(self,x):
        if self.parents[x]<0:
            return self.dist[x],x
        else:
            tmp=self.find(self.parents[x])
            self.dist[x]+=tmp[0]
            self.parents[x]=tmp[1]
            return self.dist[x],self.parents[x]
    def union(self,x,y,d):
        rx=self.find(x)[-1]
        ry=self.find(y)[-1]
        diff=d+self.dist[x]-self.dist[y]
        if rx==ry:
            if diff!=0:
                return True
            return False
        if self.ranks[ry]>self.ranks[rx]:
            rx,ry=ry,rx
            diff=-diff
        self.parents[ry]=rx
        self.dist[ry]=diff
        if self.ranks[ry]==self.ranks[rx]:
            self.ranks[rx]+=1
        return False
lrd = []
for i in range(m):
    l,r,d = list(map(int, input().split()))
    lrd.append([l,r,d])
v=UnionfindWithWeight(n)
for i in lrd:
    l, r, d = i
    if v.union(l-1,r-1,d):
        print('No')
        import sys
        sys.exit()
print('Yes')
# Original solution
import sys
def main():
    input = sys.stdin.readline
    def inputs():
        return (int(x) for x in input().split())
    N,M = inputs()
    E={i:[] for i in range(1,N+1)}
    for i in range(M):
        L,R,D = inputs()
        E[L].append((R,D))
        E[R].append((L,-D))
    visited = {i: False for i in list(E.keys())}
    dis = [0]*(N+1)
    while False in list(visited.values()):
        stk = [(list(visited.values()).index(False) + 1, -1, 0)]
        flag = True
        while stk:
            v, p, d = stk.pop()
            #print(v,p)
            if visited[v]:
                if dis[v]!=dis[p]+d:
                    print("No")
                    exit()
                continue
            visited[v] = True
            dis[v]=dis[p]+d
            for u,d in E[v]:
                if u != p:
                    stk.append((u,v,d))
    print("Yes")
main()

# Optimized solution
import sys
def main():
    input = sys.stdin.readline
    def inputs():
        return (int(x) for x in input().split())
    N,M = inputs()
    E={i:[] for i in range(1,N+1)}
    for i in range(M):
        L,R,D = inputs()
        E[L].append((R,D))
        E[R].append((L,-D))
    visited = {i: False for i in range(1,N+1)}
    dis = [0]*(N+1)
    for i in range(1,N+1):
        if not visited[i]:
            stk = [( i, -1, 0)]
            while stk:
                v, p, d = stk.pop()
                #print(v,p)
                if visited[v]:
                    if dis[v]!=dis[p]+d:
                        print("No")
                        exit()
                    continue
                visited[v] = True
                dis[v]=dis[p]+d
                for u,d in E[v]:
                    if u != p:
                        stk.append((u,v,d))
    print("Yes")
main()