Problem p03452 (python)

Fixed submission:
def solve(N, M, lrd):
    edges = {}
    nodes = {}
    for l, r, d in lrd:
        if not l in edges:
            edges[l] = {}
        if not r in edges:
            edges[r] = {}
        edges[l][r] = d
        edges[r][l] = -d
        nodes[l] = None
        nodes[r] = None
    for node in nodes:
        if nodes[node] is not None:
            continue
        nodes[node] = 0
        stack = []
        stack.append(node)
        while stack:
            node = stack.pop()
            for n, d in edges[node].items():
                if nodes[n] is None:
                    stack.append(n)
                    nodes[n] = nodes[node] + edges[node][n]
                else:
                    if nodes[n] != nodes[node] + edges[node][n]:
                        return False
    return True

if __name__ == "__main__":
    N, M = [int(x) for x in input().split()]
    lrd = []
    for i in range(M):
        lrd.append([int(x) for x in input().split()])
    if solve(N, M, lrd):
        print("Yes")
    else:
        print("No")

Buggy submission (verdict: Runtime Error):
class UnionFind:
    def __init__(self, size):
        # 負の値はルート (集合の代表) で集合の個数
        # 正の値は次の要素を表す
        self.table = [-1 for _ in range(size + 1)]

    # 集合の代表を求める
    def find(self, x):
        if self.table[x] < 0:
            return x
        else:
            # 経路の圧縮
            self.table[x] = self.find(self.table[x])
            return self.table[x]

    # 併合
    def union(self, x, y):
        s1 = self.find(x)
        s2 = self.find(y)
        if s1 != s2:
            if self.table[s1] <= self.table[s2]:
                # 小さいほうが個数が多い
                self.table[s1] += self.table[s2]
                self.table[s2] = s1
            else:
                self.table[s2] += self.table[s1]
                self.table[s1] = s2
            return True
        return False

def solve0(N, M, lrd):
    xss = []
    def getx(n):
        for xs in xss:
            if n in xs:
                return xs
        xs = {n: 0}
        xss.append(xs)
        return xs
    for l, r, d in lrd:
        lxs = getx(l)
        rxs = getx(r)
        if lxs is rxs:
            if lxs[l] != rxs[r] - d:
                return 0
        else:
            delta = lxs[l] - rxs[r] - d
            for k in lxs:
                v = lxs[k] + delta
                if k in rxs:
                    if rxs[k] != v:
                        return 0
                rxs[k] = v
            xss.remove(lxs)
    for xs in xss:
        if max(xs.values()) - min(xs.values()) > 10**9:
            return 0
    return 1

def solve(N, M, lrd):
    uf = UnionFind(N + 1)
    for l, r, d in lrd:
        uf.union(l, r)
    xs = {}
    for i, n in enumerate(uf.table):
        if i == 0:
            continue
        if n >= 0:
            n = uf.table[n]
        if not n in xs: xs[n] = {}
        xs[n][i] = None
    for l, r, d in lrd:
        for row in xs.values():
            if l in row:
                break
        if row[l] is None:
            if row[r] is None:
                row[r] = 0
            row[l] = row[r] - d
        else:
            if row[r] is None:
                row[r] = row[l] + d
            else:
                if row[l] != row[r] - d:
                    return False
    for row in xs.values():
        vs = list(row.values())
        if vs[0] is None:
            continue
        if max(vs) - min(vs) > 10**9:
            return False
    return True

N, M = [int(x) for x in input().split()]
lrd = []
for i in range(M):
    lrd.append([int(x) for x in input().split()])

#N, M = 3, 3
#lrd = [[1,2,1],[2,3,1],[1,3,2]]

#N, M = 3, 3
#lrd = [[1,2,1],[2,3,1],[1,3,5]]

#N, M = 4, 3
#lrd = [[2,1,1],[2,3,5],[3,4,2]]

#N, M = 10, 3
#lrd = [[8,7,100],[7,9,100],[9,8,100]]

#N, M = 100, 0
#lrd = []

if solve(N, M, lrd):
    print("Yes")
else:
    print("No")