#include <cassert>
#include <algorithm>
#include <cctype>
#include <complex>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <ctime>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <stack>
#include <sstream>
#include <tuple>
#include <typeinfo>
#include <unordered_set>
#include <unordered_map>
#include <vector>
using namespace std;

#define REP2(i, m, n) for(int i = (int)(m); i < (int)(n); i++)
#define REPD(i, n) for(int i = (int)(n) - 1; i >= 0; i--)
#define REP(i, n) REP2(i, 0, n)
#define ALL(c) (c).begin(), (c).end()
#define PB(e) push_back(e)
#define FOREACH(i, c) for(auto i = (c).begin(); i != (c).end(); ++i)
#define MP(a, b) make_pair(a, b)
#define BIT(n, m) (((n) >> (m)) & 1)

typedef long long ll;

template <typename S, typename T> ostream &operator<<(ostream &out, const pair<S, T> &p) {
  out << "(" << p.first << ", " << p.second << ")";
  return out;
}

template <typename T> ostream &operator<<(ostream &out, const vector<T> &v) {
  out << "[";
  REP(i, v.size()){
    if (i > 0) out << ", ";
    out << v[i];
  }
  out << "]";
  return out;
}

class UnionFind{
  int num_components;
  std::vector<int> parent;
  std::vector<int> weight;
  std::vector<int> rank;
public:
  UnionFind(int N) : num_components(N),
                     parent(std::vector<int>(N)),
                     weight(std::vector<int>(N, 1)),
                     rank(std::vector<int>(N, 0)){
    for(int i = 0; i < N; i++) parent[i] = i;
  }
  
  int find(int x){
    if(x == parent[x]) return x;
    else return parent[x] = find(parent[x]);
  }
  
  int size(int x){
    return weight[find(x)];
  }

  
  bool same(int x, int y){
    return find(x) == find(y);
  }
    
  void unite(int x, int y){
    x = find(x);
    y = find(y);
    if(x == y) return;

    num_components--;
    if(rank[x] < rank[y]){
      weight[y] += weight[x];
      parent[x] = y;
    }else{
      weight[x] += weight[y];
      parent[y] = x;
      if(rank[x] == rank[y]) rank[y]++;
    }
  }
  
  int count(){
    return num_components;
  }
};

int main(int argc, char *argv[])
{
  int N, M;
  cin >> N >> M;
  vector<vector<int>> G(N);
  vector<ll> A(N);
  vector<ll> B(N);
  vector<pair<ll, int>> vs;
  REP(i, N) {
    cin >> A[i] >> B[i];
    vs.push_back(make_pair(A[i] - B[i], i));
  }
  sort(ALL(vs));

  REP(i, M) {
    int a, b;
    cin >> a >> b;
    a--, b--;
    G[a].push_back(b);
    G[b].push_back(a);
  }

  UnionFind uf(N);
  vector<ll> sum(N, -1);
  vector<ll> dp(N, -1);

  REP(i, N) {
    int v = vs[i].second;

    vector<int> cs;
    for (const auto &w : G[v]) {
      int wc = uf.find(w);
      if (sum[wc] < 0) continue;
      cs.push_back(wc);
    }
    sort(ALL(cs));
    cs.erase(unique(ALL(cs)), cs.end());

    ll csum = 0;
    for (int c : cs) {
      csum += sum[c];
    }

    if (int(cs.size()) == 0) {
      dp[uf.find(v)] = max(A[v], B[v]);
      sum[uf.find(v)] = B[v];
    } else {
      ll res = csum + max(A[v], B[v]);
      for (int c : cs) {
        res = min(res, max(A[v], dp[c] + B[v]) + csum - sum[c]);
      }

      for (int w : G[v]) {
        int wc = uf.find(w);
        if (sum[wc] < 0) continue;
        uf.unite(v, wc);
      }
      sum[uf.find(v)] = csum + B[v];
      dp[uf.find(v)] = res;
    }
  }
  cout << dp[uf.find(vs[N - 1].second)] << endl;
}


Measured memory_bytes: 12144