Problem:
Score : 1000 points

Problem Statement

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 1

4 5
3 1
1 2
4 1
6 2
1 2
2 3
2 4
1 4
3 4

Sample Output 1

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.

Move to Vertex 2. This is possible since you have not less than 1 yen.

Donate 2 yen to Vertex 2. Now you have 0 yen.

If you have less than 6 yen initially, you cannot win the game. Thus, the answer is 6.

Sample Input 2

5 8
6 4
15 13
15 19
15 1
20 7
1 3
1 4
1 5
2 3
2 4
2 5
3 5
4 5

Sample Output 2

44

Sample Input 3

9 10
131 2
98 79
242 32
231 38
382 82
224 22
140 88
209 70
164 64
6 8
1 6
1 4
1 3
4 7
4 9
3 7
3 9
5 9
2 5

Sample Output 3

582

Solution in Java8 (OpenJDK 1.8.0) (judge verdict: Wrong Answer)

import java.util.*;

public class Main {

	public static void main(String args[]) {
		int rep = 1;
		if (args.length > 0) {
			if( args[0].equals("gen") ) {
				(new Main()).gen();
				return;
			}
			rep = Integer.parseInt(args[0]);
		}
		(new Main()).__solve(rep);
	}
	
	void gen() {
		int N = 100000;
		int E = 100000;
		Random rand = new Random();
		System.out.println(N + " " + E);
		for( int i = 0; i < N; ++i ) {
			int R = rand.nextInt(1000000000) + 1;
			int P = rand.nextInt(1000000000) + 1;
			System.out.println(R + " " + P);
		}
		for( int i = 0; i < E; ++i ) {
			int F = rand.nextInt(i + 1) + 1; 
			int T = i + 2;
			if( i == E - 1 ) {
				T = rand.nextInt(i + 1) + 1; 
			}
			System.out.println(F + " " + T);
		}
	}

	void __solve(int rep) {

		try (Scanner cin = new Scanner(System.in);) {

			for (int i = 0; i < rep; ++i) {
				TTinit();
				__solve(cin);
//				TTstep();
			}

		}

	}
	
	long TTstart;
	void TTinit() {
		TTstart = System.currentTimeMillis();
	}
	
	void TTstep() {
		System.err.println("step: " + (System.currentTimeMillis() - TTstart));
	}

	void __solve(Scanner cin) {
		
		int N = cin.nextInt();
		int E = cin.nextInt();
		long sum = 0;
		
		Pair pair[] = new Pair[N];
		
		long ret = 0;
		Node nodes[] = new Node[N];
		for( int i = 0; i < N; ++i ) {
			nodes[i] = new Node(cin.nextInt(), cin.nextInt());
			sum += nodes[i].pay;
			if( nodes[i].req > nodes[i].pay ) {
				ret = Math.max(ret, nodes[i].req - nodes[i].pay);
			}
			pair[i] = new Pair(i, Math.max(0, nodes[i].req - nodes[i].pay));
		}

		for (int i = 0; i < E; ++i) {
			int F = cin.nextInt() - 1;
			int T = cin.nextInt() - 1;
			nodes[F].add(T);
			nodes[T].add(F);
		}
		
		boolean skip[] = new boolean[N];
		
		Arrays.sort(pair);
		for( int i = 0; i < Math.min(N, 200); ++i ) {
			if( skip[i] ) { continue; }
			ret = Math.min(ret, solve(nodes, N, pair[i].key, ret, skip));
			skip[pair[i].key] = true; 
		}
		
		for( int i = 0; i < N; ++i ) {
			if( skip[i] ) { continue; }
//			ret = Math.min(ret, solve(nodes, N, i, ret, skip));
		}
		
		System.out.println(ret + sum);
		
	}
	
	long solve(Node nodes[], int N, int start, long best, boolean skip[]) {
		boolean visited[] = new boolean[N];
		visited[start] = true;
		long ret = Math.max(0, nodes[start].req - nodes[start].pay);
		if( ret >= best ) { return best; }
		long total = nodes[start].pay;
		
		Set<Integer> reach = new HashSet<Integer>();
		nodes[start].merge(reach, visited);
		
		int rest = N - 1;
		boolean skipF = false;
		
		while( rest > 0 ) {
			List<Integer> add = new ArrayList<Integer>();
			long diff = best;
			for( int next : reach ) {
				if( visited[next] ) {
					throw new RuntimeException("implementation error...");
				}
				if( total + ret + nodes[next].pay >= nodes[next].req ) {
					total += nodes[next].pay;
					add.add(next);
				}
				else {
					diff = Math.min(diff, nodes[next].req - (total + ret + nodes[next].pay));
				}
			}
			if( add.isEmpty() ) {
				ret += diff;
				if( ret >= best ) { return best; }
				skipF = true;
				continue;
			}
			for( int next : add ) {
				visited[next] = true;
				if( skipF ) {
					skip[next] = true;
				}
			}
			for( int next : add ) {
				nodes[next].merge(reach, visited);
			}
			for( int next : add ) {
				reach.remove(next);
			}
			rest -= add.size();
			skipF = false;
		}
		
		return ret;
		
	}
	
	class Node {
		
		int req;
		int pay;
		
		List<Integer> edge;
		
		Node(int req, int pay) {
			this.req = req;
			this.pay = pay;
			edge = new ArrayList<Integer>();
		}
		
		void add(int target) {
			edge.add(target);
		}
		
		void merge(Set<Integer> reach, boolean visited[]) {
			for( int node : edge ) {
				if( visited[node] ) { continue; }
				reach.add(node);
			}
		}
		
	}
	
	class Pair implements Comparable<Pair> {
		
		int key;
		int value;
		
		Pair(int key, int value) {
			this.key = key;
			this.value = value;
		}
		
		@Override
		public int compareTo(Pair p) {
			if( p.value > value ) { return -1; }
			if( p.value < value ) { return 1; }
			if( p.key > key ) { return -1; }
			if( p.key < key ) { return 1; }
			return 0;
		}
		
	}
	
}