#include <bits/stdc++.h>
#define FOR(i, begin, end) for(int i=(begin);i<(end);i++)
#define REP(i, n) FOR(i,0,n)
#define IFOR(i, begin, end) for(int i=(end)-1;i>=(begin);i--)
#define IREP(i, n) IFOR(i,0,n)
#define Sort(a) sort(a.begin(), a.end())
#define Reverse(a) reverse(a.begin(), a.end())
#define Lower_bound(v, x) distance(v.begin(), lower_bound(v.begin(), v.end(), x))
#define Upper_bound(v, x) distance(v.begin(), upper_bound(v.begin(), v.end(), x))
#define Max(a, b) a = max(a, b)
#define Min(a, b) a = min(a, b)
#define Ans(f, y, n) if(f) cout << y << endl; else cout << n << endl;
#define int long long
#define INF 1000000000000000000
using namespace std;

using vec = vector<int>;
using mat = vector<vec>;
using Pii = pair<int, int>;
using PiP = pair<int, Pii>;
using PPi = pair<Pii, int>;
using bools = vector<bool>;

template<typename T>
void readv(vector<T> &a){ REP(i, a.size()) cin >> a[i]; }
void readi(vector<int> &a){ REP(i, a.size()){cin >> a[i]; a[i]--;} }
template<typename T>
void debug(vector<vector<T>> m){ REP(i, m.size()){ REP(j, m[i].size()){ cout << m[i][j] << ","; } cout << endl;} }

void unite_que(priority_queue<Pii, vector<Pii>, greater<Pii>> &q1, priority_queue<Pii, vector<Pii>, greater<Pii>> &q2){
    if(q2.size() > q1.size()) q1.swap(q2);
    while(!q2.empty()){
        q1.push(q2.top());
        q2.pop();
    }
}

class Union_find
{
public:
    vector<int> par;
    vector<int> sz, dat;
    vector<priority_queue<Pii, vector<Pii>, greater<Pii>>> que;

    Union_find(int N){
        par = vector<int>(N);
        //REP(i, N) par[i] = i;
        sz = vector<int>(N);
        dat = vector<int>(N);
        //dat = v;
        que = vector<priority_queue<Pii, vector<Pii>, greater<Pii>>>(N);
    }

    void init(vector<int> v, int N){
        REP(i, N) par[i] = i;
        fill(sz.begin(), sz.end(), 1);
        REP(i, N) dat[i] = v[i];
    }

    int find(int x){
        if(par[x] == x) return x;
        else return par[x] = find(par[x]);
    }

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

        if(sz[x] < sz[y]) swap(x, y);

        par[y] = x;
        sz[x] += sz[y];
        dat[x] += dat[y];
        unite_que(que[x], que[y]);
    }

    bool is_union(int x, int y){
        x = find(x);
        y = find(y);
        return x == y;
    }

    int union_size(int x){
        return sz[find(x)];
    }

};

struct edge{int to, cost;};

class Graph
{
public:
    int V;
    vector<vector<edge>> G;

    Graph(int V): V(V){
        G = vector<vector<edge>>(V, vector<edge>(0));
    }

    void add_edge(int from, int to, int cost){
        G[from].push_back(edge({to, cost}));
    }

    void add_edge2(int v1, int v2, int cost){
        add_edge(v1, v2, cost);
        add_edge(v2, v1, cost);
    }

    void dfs(int v, int w, Union_find &UF){
        if(UF.union_size(v) > 1) return;
        while(!UF.que[UF.find(v)].empty()){
            int par = UF.find(v);
            Pii p = UF.que[par].top();
            if(p.first > UF.dat[par] + w) break;
            UF.que[par].pop();
            UF.unite(par, p.second);
        }
    }

};

void init(Graph &G, Union_find &UF, vec &A, int N){
    //UF.que = vector<priority_queue<Pii, vector<Pii>, greater<Pii>>>(N);
    REP(i, N){
        UF.que[i] = priority_queue<Pii, vector<Pii>, greater<Pii>>();
        REP(k, G.G[i].size()) UF.que[i].push(Pii(A[G.G[i][k].to], G.G[i][k].to));
    }
}

signed main(){

    int N, M; cin >> N >> M;
    Graph G(N);
    vec A(N), B(N);
    int S = 0;
    REP(i, N){
        cin >> A[i] >> B[i];
        S += B[i];
        A[i] -= B[i];
    }
    int U, V;
    REP(i, M){
        cin >> U >> V;
        G.add_edge2(U - 1, V - 1, 0);
    }
    if(N == 1){
        cout << max(A[0] + B[0], B[0]) << endl;
        return 0;
    }

    int w1 = -1, w2 = 1000000000;
    Union_find UF(N);
    while(w2 - w1 > 1){
        int w = (w1 + w2 + 1) / 2;
        UF.init(B, N);
        init(G, UF, A, N);
        REP(i, N) if(w >= A[i]) G.dfs(i, w, UF);
        //cout << w << "," << UF.union_size(0) << endl;
        if(UF.union_size(0) == N) w2 = w;
        else w1 = w;
    }
    cout << w2 + S << endl;

    return 0;
}


Measured memory_bytes: 23024