Buggy python submission (verdict: Runtime Error):
# -*- coding: utf-8 -*-

"""
参考：https://www.hamayanhamayan.com/entry/2018/01/28/231916
・深さ優先
・幅優先とほとんど一緒だけど練習用にこっちも書いた。
"""

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

l_edges = [[] for i in range(N)]
r_edges = [[] for i in range(N)]
for i in range(M):
    l, r, d = map(int, input().split())
    l_edges[l-1].append((r-1, d))
    r_edges[r-1].append((l-1, d))

# 訪問済メモ
visited = [0] * N

def dfs(cur):
    visited[cur] = 1
    # 左から見た右側を確認
    for r, d in l_edges[cur]:
        # 訪問済なら矛盾がないか検証する
        if visited[r]:
            if pos[r] - pos[cur] != d:
                print('No')
                exit()
        # 未訪問なら今回の情報を記録する
        else:
            visited[r] = 1
            pos[r] = pos[cur] + d
            # 確認した位置を次の現在位置として見に行く
            dfs(r)
    # 右から見た左側を確認
    for l, d in r_edges[cur]:
        if visited[l]:
            if pos[cur] - pos[l] != d:
                print('No')
                exit()
        else:
            visited[l] = 1
            pos[l] = pos[cur] - d
            dfs(l)

for i in range(N):
    # 訪問済(確認済)でなければ走破しに行く
    if not visited[i]:
        # この開始位置を基準とした相対位置を記録する
        pos = {i: 0}
        dfs(i)
        pos = {}
# 最後まで矛盾がなければOK
print('Yes')


Fixed submission:
# -*- coding: utf-8 -*-

"""
参考：http://hamko.hatenadiary.jp/entry/2018/01/30/210057
　　　http://at274.hatenablog.com/entry/2018/02/03/140504
・重み付きUnion-Find木
"""

class WeightedUnionFind:
    def __init__(self, n):
        self.par = [i for i in range(n+1)]
        self.rank = [0] * (n+1)
        # 根への距離を管理
        self.weight = [0] * (n+1)

    # 検索
    def find(self, x):
        if self.par[x] == x:
            return x
        else:
            y = self.find(self.par[x])
            # 親への重みを追加しながら根まで走査
            self.weight[x] += self.weight[self.par[x]]
            self.par[x] = y
            return y

    # 併合
    def union(self, x, y, w):
        rx = self.find(x)
        ry = self.find(y)
        # xの木の高さ < yの木の高さ
        if self.rank[rx] < self.rank[ry]:
            self.par[rx] = ry
            self.weight[rx] = w - self.weight[x] + self.weight[y]
        # xの木の高さ ≧ yの木の高さ
        else:
            self.par[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)

    # xからyへのコスト
    def diff(self, x, y):
        return self.weight[x] - self.weight[y]

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

wuf = WeightedUnionFind(N)
for i in range(M):
    x, y, w = map(int, input().split())
    # 同じ集合に属する場合は
    if wuf.same(x, y):
        # 記録された距離と今回の情報に矛盾がないか確認
        if wuf.diff(x, y) != w:
            print('No')
            exit()
    wuf.union(x, y, w)
# 全部無矛盾で木が構築できればOK
print('Yes')

Buggy python submission (verdict: Time Limit Exceeded):
# -*- coding: utf-8 -*-

from collections import deque

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

edges = [None] * M
for i in range(M):
    l, r, d = map(int, input().split())
    edges[i] = (l-1, r-1, d)

# 訪問済メモ
visited = [0] * N

def bfs(start):
    # この開始位置を基準とした相対位置を記録する
    pos = {start: 0}
    que = deque()
    que.append(start)
    visited[start] = 1
    while len(que) != 0:
        cur = que.popleft()
        # 辺のループ
        for l, r, d in edges:
            # 左から見た右側を確認
            if l == cur:
                # 訪問済なら矛盾がないか検証する
                if visited[r]:
                    if pos[r] - pos[l] != d:
                        print('No')
                        exit()
                # 未訪問なら今回の情報を記録する
                else:
                    visited[r] = 1
                    pos[r] = pos[l] + d
                    # 次回以降、開始位置として使うのでキューに詰める
                    que.append(r)
            # 右から見た左側を確認
            elif r == cur:
                if visited[l]:
                    if pos[r] - pos[l] != d:
                        print('No')
                        exit()
                else:
                    visited[l] = 1
                    pos[l] = pos[r] - d
                    que.append(l)

for i in range(N):
    # 訪問済(確認済)でなければ走破しに行く
    if not visited[i]:
        bfs(i)
# 最後まで矛盾がなければOK
print('Yes')


Fixed submission:
# -*- coding: utf-8 -*-

"""
参考：http://hamko.hatenadiary.jp/entry/2018/01/30/210057
　　　http://at274.hatenablog.com/entry/2018/02/03/140504
・重み付きUnion-Find木
"""

class WeightedUnionFind:
    def __init__(self, n):
        self.par = [i for i in range(n+1)]
        self.rank = [0] * (n+1)
        # 根への距離を管理
        self.weight = [0] * (n+1)

    # 検索
    def find(self, x):
        if self.par[x] == x:
            return x
        else:
            y = self.find(self.par[x])
            # 親への重みを追加しながら根まで走査
            self.weight[x] += self.weight[self.par[x]]
            self.par[x] = y
            return y

    # 併合
    def union(self, x, y, w):
        rx = self.find(x)
        ry = self.find(y)
        # xの木の高さ < yの木の高さ
        if self.rank[rx] < self.rank[ry]:
            self.par[rx] = ry
            self.weight[rx] = w - self.weight[x] + self.weight[y]
        # xの木の高さ ≧ yの木の高さ
        else:
            self.par[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)

    # xからyへのコスト
    def diff(self, x, y):
        return self.weight[x] - self.weight[y]

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

wuf = WeightedUnionFind(N)
for i in range(M):
    x, y, w = map(int, input().split())
    # 同じ集合に属する場合は
    if wuf.same(x, y):
        # 記録された距離と今回の情報に矛盾がないか確認
        if wuf.diff(x, y) != w:
            print('No')
            exit()
    wuf.union(x, y, w)
# 全部無矛盾で木が構築できればOK
print('Yes')