human
I found an interesting problem on https://atcoder.jp/contests/arc098/tasks/arc098_d:
There is a simple undirected graph with N vertices and M edges.
The vertices are numbered 1 through N, and the edges are numbered 1 through M.
Edge i connects Vertex U_i and V_i.
Also, Vertex i has two predetermined integers A_i and B_i.
You will play the following game on this graph.
First, choose one vertex and stand on it, with W yen (the currency of Japan) in your pocket.
Here, A_s \leq W must hold, where s is the vertex you choose.
Then, perform the following two kinds of operations any number of times in any order:
 - Choose one vertex v that is directly connected by an edge to the vertex you are standing on, and move to vertex v. Here, you need to have at least A_v yen in your pocket when you perform this move.
 - Donate B_v yen to the vertex v you are standing on. Here, the amount of money in your pocket must not become less than 0 yen.
You win the game when you donate once to every vertex.
Find the smallest initial amount of money W that enables you to win the game.

-----Constraints-----
 - 1 \leq N \leq 10^5
 - N-1 \leq M \leq 10^5
 - 1 \leq A_i,B_i \leq 10^9
 - 1 \leq U_i < V_i \leq N
 - The given graph is connected and simple (there is at most one edge between any pair of vertices).

-----Input-----
Input is given from Standard Input in the following format:
N M
A_1 B_1
A_2 B_2
:
A_N B_N
U_1 V_1
U_2 V_2
:
U_M V_M

-----Output-----
Print the smallest initial amount of money W that enables you to win the game.

-----Sample Input-----
4 5
3 1
1 2
4 1
6 2
1 2
2 3
2 4
1 4
3 4

-----Sample Output-----
6

If you have 6 yen initially, you can win the game as follows:
 - Stand on Vertex 4. This is possible since you have not less than 6 yen.
 - Donate 2 yen to Vertex 4. Now you have 4 yen.
 - Move to Vertex 3. This is possible since you have not less than 4 yen.
 - Donate 1 yen to Vertex 3. Now you have 3 yen.
 - Move to Vertex 2. This is possible since you have not less than 1 yen.
 - Move to Vertex 1. This is possible since you have not less than 3 yen.
 - Donate 1 yen to Vertex 1. Now you have 2 yen.
...

I tried it in Python, but could not do it. Can you solve it?

Give me a Python program to find the smallest initial amount of money W that enables you to win the game?
assistant
#Here is Python program to find the smallest initial amount of money W that enables you to win the game.

class dsu:
    def __init__(self, n=0):
        self._n = n
        self.parent_or_size = [-1] * n
    
    def merge(self, a: int, b: int) -> int:
        x = self.leader(a)
        y = self.leader(b)
        if x == y:
            return x
        if self.parent_or_size[x] > self.parent_or_size[y]:
            x, y = y, x
        self.parent_or_size[x] += self.parent_or_size[y]
        self.parent_or_size[y] = x
        return x
    
    def same(self, a: int, b: int) -> bool:
        return self.leader(a) == self.leader(b)
    
    def leader(self, a: int) -> int:
        x = a
        while self.parent_or_size[x] >= 0:
            x = self.parent_or_size[x]
        while a != x:
            self.parent_or_size[a], a = x, self.parent_or_size[a]
        return x
    
    def size(self, a: int) -> int:
        return -self.parent_or_size[self.leader(a)]
    
    def groups(self):
        g = [[] for _ in range(self._n)]
        for i in range(self._n):
            g[self.leader(i)].append(i)
        return list(c for c in g if c)

n, m = list(map(int, input().split()))
vdata = [] # (required, gain)
for _ in range(n):
    a, b = list(map(int, input().split()))
    vdata.append((max(a - b, 0), b))
to = [[] for _ in range(n)]
for _ in range(m):
    u, v = list(map(int, input().split()))
    u -= 1; v -= 1
    to[u].append(v)
    to[v].append(u)
s = dsu(n)
dp = vdata.copy() # (extra, tot_gain)
visited = [False] * n
for u in sorted(list(range(n)), key=lambda i: vdata[i][0]):
    req, gain = vdata[u]
    frm = {u}
    for v in to[u]:
        if visited[v]:
            frm.add(s.leader(v))
    mnextra = 10 ** 18
    for v in frm:
        e, g = dp[v]
        e += max(req - (e + g), 0)
        if e < mnextra:
            mnextra, mni = e, v
    extra, tot_gain = mnextra, sum(dp[v][1] for v in frm)
    for v in frm:
        s.merge(u, v)
    dp[s.leader(u)] = extra, tot_gain
    visited[u] = True
ans = sum(dp[s.leader(0)])
print(ans)