#include <bits/stdc++.h>
using namespace std;
#define FOR(i, j, k) for(int i=(j); i<=(k); i++)
#define FFOR(i, j, k) for(int i=(j); i<(k); i++)
#define DFOR(i, j, k) for(int i=(j); i>=(k); i--)
#define bug(x) cerr<<#x<<" = "<<(x)<<'\n'
#define pb push_back
#define mp make_pair
#define bit(s, i) (((s)>>(i))&1LL)
#define mask(i) ((1LL<<(i)))
#define builtin_popcount __builtin_popcountll
#define __builtin_popcount __builtin_popcountll
using ll=long long; using ld=long double;
mt19937_64 rng(chrono::high_resolution_clock::now().time_since_epoch().count()); const ld pi=acos(0)*2;
template <typename T> inline void read(T &x){char c; bool nega=0; while((!isdigit(c=getchar()))&&(c!='-')); if(c=='-'){nega=1; c=getchar();} x=c-48; while(isdigit(c=getchar())) x=x*10+c-48; if(nega) x=-x;}
template <typename T> inline void writep(T x){if(x>9) writep(x/10); putchar(x%10+48);}
template <typename T> inline void write(T x){if(x<0){ putchar('-'); x=-x;} writep(x);}
template <typename T> inline void writeln(T x){write(x); putchar('\n');}
template <typename CT, typename T> inline void reset_container(CT &c, int sz, T v){c.resize(sz); for(auto &x: c) x=v;}
#define taskname "B3"
int n, m;
int c[101][101];
int s, b, k;
vector <int> ship_at[101];
vector <int> base_at[101];
class ship{
public:
    int x, a, f, p;
    void input(int id){
        read(x);
        read(a);
        read(f);
        read(p);
        ship_at[x].pb(id);
    }
} S[100001];
class base{
public:
    int x, d, g;
    void input(int id){
        read(x);
        read(d);
        read(g);
        base_at[x].pb(id);
    }
} B[100001];
int r[100001];
vector <int> g[100001];
vector <int> cc[100001];
int root(int u){
    if(r[u]<0) return u;
    return r[u]=root(r[u]);
}
void unite(int u, int v){
    u=root(u);
    v=root(v);
    if(u==v) return;
    if(r[u]>r[v]) swap(u, v);
    r[u]+=r[v];
    r[v]=u;
}
ll p[100001];
class maxflow{
public:
    class edge{
    public:
        using pointer=edge*;
        int v;
        ll c;
        pointer rev;
        edge(int v, ll c){
            this->v=v;
            this->c=c;
        }
    };
    vector <edge::pointer> g[100002];
    void reset(){
//        for(int u: vertices) g[u].clear();
        g[0].clear();
        g[100001].clear();
        flow=0;
    }
//    void reset(vector <int> &vertices){
//        for(int u: vertices) g[u].clear();
//        g[0].clear();
//        g[100001].clear();
//        flow=0;
//    }
    void add_edge(int u, int v, ll c){
        g[u].pb(new edge(v, c));
        g[v].pb(new edge(u, 0));
        g[u].back()->rev=g[v].back();
        g[v].back()->rev=g[u].back();
    }
    edge::pointer trace[100002];
    int done[100002];
    int t;
    bool bfs(){
        t++;
        queue <int> q;
        q.push(0);
        done[0]=t;
        while(!q.empty()){
            int u=q.front();
            q.pop();
            for(auto e: g[u]) if(e->c) if(done[e->v]!=t){
                done[e->v]=t;
                q.push(e->v);
                trace[e->v]=e;
                if(e->v==100001) return 1;
            }
        }
        return 0;
    }
    ll flow;
    void increase_flow(){
        int u=100001;
        ll f=1e18;
        while(u){
            f=min(f, trace[u]->c);
            u=trace[u]->rev->v;
        }
        flow+=f;
        u=100001;
        while(u){
            trace[u]->c-=f;
            trace[u]->rev->c+=f;
            u=trace[u]->rev->v;
        }
    }
    ll get_flow(){
        while(bfs()) increase_flow();
        return flow;
    }
} MF;
ll get_profit(int i){
    MF.reset();
    ll prof=0;
    for(int u: cc[i]){
        if(p[u]>=0){
            prof+=p[u];
            MF.add_edge(0, u, p[u]);
        }
        else{
//            prof-=p[u];
            MF.add_edge(u, 100001, -p[u]);
        }
        for(int v: g[u]) MF.add_edge(u, v, 1e15);
    }
    ll flow=MF.get_flow();
    prof-=flow;
    return max(0LL, prof);
}
int main(){
    #ifdef Aria
        if(fopen(taskname".in", "r"))
            freopen(taskname".in", "r", stdin);
    #endif // Aria
    read(n);
    read(m);
    FOR(i, 1, n) FOR(j, 1, n) if(i!=j) c[i][j]=(1e9)+420;
    FOR(i, 1, m){
        int u, v;
        read(u);
        read(v);
        if(u!=v) c[u][v]=c[v][u]=1;
    }
    FOR(k, 1, n) FOR(i, 1, n) FOR(j, 1, n) c[i][j]=min(c[i][j], c[i][k]+c[k][j]);
    read(s);
    read(b);
    read(k);
    FOR(i, 1, s) S[i].input(i);
    FOR(i, 1, b) B[i].input(i);
    FOR(i, 1, s) r[i]=-1;
    FOR(i, 1, k){
        int u, v;
        read(u);
        read(v);
        g[u].pb(v);
        unite(u, v);
    }
    FOR(i, 1, n){
        sort(base_at[i].begin(), base_at[i].end(), [](int X, int Y){
            return B[X].d<B[Y].d;
        });
        FFOR(j, 1, base_at[i].size()) B[base_at[i][j]].g=max(B[base_at[i][j]].g, B[base_at[i][j-1]].g);
    }
    FOR(i, 1, s){
        ll prof=-1e15;
        FOR(v, 1, n) if(c[v][S[i].x]<=S[i].f){
            int low=0, high=((int)base_at[v].size())-1, mid, res=-1;
            while(low<=high){
                mid=(low+high)/2;
                if(B[base_at[v][mid]].d<=S[i].a){
                    res=mid;
                    low=mid+1;
                }
                else high=mid-1;
            }
            if(res!=-1) prof=max(prof, (ll)(B[base_at[v][res]].g-S[i].p));
        }
        p[i]=prof;
    }
    ll res=0;
//    FOR(i, 1, s) cerr<<p[i]<<" \n"[i==s];
    FOR(i, 1, s) cc[root(i)].pb(i);
    FOR(i, 1, s) if(i==root(i)) res+=get_profit(i);
    writeln(res);
}

#include<bits/stdc++.h>

using ll=long long;
const ll LINF=1e13;

using namespace std;
namespace ProconLib{
    template<typename cost_t=long long,bool hasNegativeCost=false,cost_t INF=LINF>
    class Flow{
        public:
        struct Edge{
            int to;
            cost_t cap,rev;
            cost_t cost;
        };
        using Edges=vector<Edge>;
        using Graph=vector<Edges>;

        private:
        int N;
        Graph g;
        vector<int> level;
        vector<int> iter;
        void bfs(int s);
        cost_t dfs(int v,int t,cost_t f);

        public:
        Flow(int N):N(N),g(N){};
        void addEdge(int from,int to,cost_t cap);
        void addEdge(int from,int to,cost_t cap,cost_t cost);
        cost_t maxFlow(int s,int t);
        cost_t minCostFlow(int s,int t,cost_t f);
    };

    template<typename cost_t,bool hasNegativeCost,cost_t INF>
    void Flow<cost_t,hasNegativeCost,INF>::addEdge(int from,int to,cost_t cap){
        g[from].push_back({to,cap,int(g[to].size()),0});
        g[to].push_back({from,cost_t(0),int(g[from].size())-1,0});
    }

    template<typename cost_t,bool hasNegativeCost,cost_t INF>
    void Flow<cost_t,hasNegativeCost,INF>::addEdge(int from,int to,cost_t cap,cost_t cost){
        g[from].push_back({to,cap,int(g[to].size()),cost});
        g[to].push_back({from,cost_t(0),int(g[from].size())-1,-cost});
    }

    template<typename cost_t,bool hasNegativeCost,cost_t INF>
    cost_t Flow<cost_t,hasNegativeCost,INF>::maxFlow(int s,int t){
        cost_t flow=0;
        while(true){
            bfs(s);
            if(level[t]<0) return flow;
            iter.assign(N,0);
            cost_t f;
            while((f=dfs(s,t,INF))>0){
                flow+=f;
            }
        }
    }
    template<typename cost_t,bool hasNegativeCost,cost_t INF>
    void Flow<cost_t,hasNegativeCost,INF>::bfs(int s){
        level.assign(N,-1);
        queue<int> que;
        level[s]=0;
        que.push(s);
        while(!que.empty()){
            int v=que.front(); que.pop();
            for(int i=0;i<g[v].size();i++){
                Edge &e=g[v][i];
                if(e.cap>0 && level[e.to]<0){
                    level[e.to]=level[v]+1;
                    que.push(e.to);
                }
            }
        }
    }
    template<typename cost_t,bool hasNegativeCost,cost_t INF>
    cost_t Flow<cost_t,hasNegativeCost,INF>::dfs(int v,int t,cost_t f){
        if(v==t) return f;
        for(int& i=iter[v];i<g[v].size();i++){
            Edge& e=g[v][i];
            if(e.cap>0 && level[v]<level[e.to]){
                cost_t d=dfs(e.to,t,min(f,e.cap));
                if(d>0){
                    e.cap-=d;
                    g[e.to][e.rev].cap+=d;
                    return d;
                }
            }
        }
        return 0;
    }

    template<typename cost_t,bool hasNegativeCost,cost_t INF>
    cost_t Flow<cost_t,hasNegativeCost,INF>::minCostFlow(int s,int t,cost_t f){
        using P=pair<cost_t,int>;
        cost_t res=0;
        vector<cost_t> h(N,0);
        vector<int> used(N),preve(N),prevv(N);
        vector<cost_t> dist(N);
        while(f>0){
            fill(dist.begin(),dist.end(),INF);
            dist[s]=0;
            if(!hasNegativeCost){
                //Dijkstra
                fill(used.begin(),used.end(),0);
                priority_queue<P,vector<P>,greater<P>> que;
                que.push(make_pair(cost_t(0),s));
                while(!que.empty()){
                    P p=que.top(); que.pop();
                    int v=p.second;
                    if(used[v]) continue;
                    used[v]=true;
                    for(int i=0;i<g[v].size();i++){
                        Edge &e=g[v][i];
                        if(e.cap>0 && dist[e.to]>dist[v]+e.cost+h[v]-h[e.to]){
                            dist[e.to]=dist[v]+e.cost+h[v]-h[e.to];
                            prevv[e.to]=v;
                            preve[e.to]=i;
                            que.push(make_pair(dist[e.to],e.to));
                        }
                    }
                }
            }else{
                //Bermanford
                bool update=true;
                while(update){
                    update=false;
                    for(int v=0;v<N;v++){
                        if(dist[v]==INF) continue;
                        for(int i=0;i<g[v].size();i++){
                            Edge &e=g[v][i];
                            if(e.cap>0 && dist[e.to]>dist[v]+e.cost){
                                dist[e.to]=dist[v]+e.cost;
                                prevv[e.to]=v;
                                preve[e.to]=i;
                                update=true;
                            }
                        }
                    }
                }
            }

            if(dist[t]==INF){
                return -1;
            }
            if(!hasNegativeCost){
                for(int v=0;v<N;v++) h[v]+=dist[v];
            }
            cost_t d=f;
            for(int v=t;v!=s;v=prevv[v]){
                d=min(d,g[prevv[v]][preve[v]].cap);
            }
            f-=d;
            if(!hasNegativeCost){
                res+=d*h[t];
            }else{
                res+=d*dist[t];
            }
            for(int v=t;v!=s;v=prevv[v]){
                Edge& e=g[prevv[v]][preve[v]];
                e.cap-=d;
                g[v][e.rev].cap+=d;
            }
        }
        return res;
    }
}

struct Spaceship{
  int x,a,f,p;
};
struct Base{
  int x,d,g;
};

using namespace ProconLib;

using vvi=vector<vector<int>>;

void dfs(int v,vvi &g,vector<int>& used,vector<int>& vs){
  used[v]=true;
  vs.push_back(v);
  for(auto to:g[v]){
    if(used[to]) continue;
    dfs(to,g,used,vs);
  }
}

int main(){
  // Input
  int n,m;
  cin>>n>>m;

  vector<vector<int>> dist(n,vector<int>(n,1e9+5));
  for(int i=0;i<m;i++){
    int u,v;
    cin>>u>>v; u--,v--;
    dist[u][v]=1;
    dist[v][u]=1;
  }
  for(int i=0;i<n;i++) dist[i][i]=0;

  int s,b,k;
  cin>>s>>b>>k;

  vector<Spaceship> ship(s);
  for(int i=0;i<s;i++){
    cin>>ship[i].x>>ship[i].a>>ship[i].f>>ship[i].p,ship[i].x--;
  }

  vector<Base> base(b);
  for(int i=0;i<b;i++){
    cin>>base[i].x>>base[i].d>>base[i].g; base[i].x--;
  }

  vvi sg(s);
  for(int i=0;i<k;i++){
    int s1,s2; cin>>s1>>s2;
    s1--,s2--;
    sg[s1].push_back(s2);
  }

  // wartial-floid
  for(int k=0;k<n;k++){
    for(int i=0;i<n;i++){
      for(int j=0;j<n;j++){
	dist[i][j]=min(dist[i][j],dist[i][k]+dist[k][j]);
      }
    }
  }

  vector<ll> profit(s,-LINF);

  // set sorted by d
  vector<vector<int>> bids(n);
  for(int i=0;i<b;i++){
    bids[base[i].x].push_back(i);
  }
  auto cmp=[&](int lhs,int rhs){
    return base[lhs].d<base[rhs].d;
  };
  for(int i=0;i<n;i++) sort(bids[i].begin(),bids[i].end(),cmp);
  vector<vector<int>> accMax(n);
  for(int i=0;i<n;i++){
    accMax[i].resize(bids[i].size()+1);
    for(int j=0;j<bids[i].size();j++){
      accMax[i][j+1]=max(accMax[i][j],base[bids[i][j]].g);
    }
  }

  // calc profit
  for(int i=0;i<s;i++){
    int x=ship[i].x;
    for(int v=0;v<n;v++){
      if(dist[x][v]<=ship[i].f){
	int lb=-1,ub=bids[v].size();
	while(ub-lb>1){
	  int mid=(lb+ub)/2;
	  if(base[bids[v][mid]].d<=ship[i].a) lb=mid;
	  else ub=mid;
	}
	ll sc=accMax[v][ub]-ship[i].p;
	if(ub>0) profit[i]=max(profit[i],sc);
      }
    }
  }

  // should check profit

  auto doFlow=[&](const vvi& graph,const vector<ll>& mpPro){
    int n=graph.size();
    const int S=n;
    const int T=n+1;
    Flow<ll> flow(n+2);
    ll sum=0;
    for(int i=0;i<n;i++){
      if(mpPro[i]>0){
	sum+=mpPro[i];
	flow.addEdge(S,i,mpPro[i]);
	flow.addEdge(i,T,0);
      }
      else{
	flow.addEdge(S,i,0);
	flow.addEdge(i,T,-mpPro[i]);
      }
    }
    for(int i=0;i<n;i++){
      for(auto to:graph[i]){
	flow.addEdge(i,to,LINF);
      }
    }
    return sum-flow.maxFlow(S,T);
  };

  // make undirected Graph
  vvi undirSG(s);
  for(int i=0;i<s;i++){
    for(auto to:sg[i]){
      undirSG[i].push_back(to);
      undirSG[to].push_back(i);
    }
  }

  ll res=0;
  vector<int> used(s);
  for(int i=0;i<s;i++){
    if(!used[i]){
      vector<int> vs;
      dfs(i,undirSG,used,vs);
      if(vs.size()==1){
	if(profit[i]>0) res+=profit[i];
	continue;
      }
      map<int,int> mp;
      int id=0;
      for(auto v:vs){
	mp[v]=id++;
      }
      vvi mapG(id);
      vector<ll> mpPro(id);
      for(auto v:vs){
	mpPro[mp[v]]=profit[v];
	for(auto to:sg[v]){
	  mapG[mp[v]].push_back(mp[to]);
	}
      }
      res+=doFlow(mapG,mpPro);
    }
  }

  cout<<res<<endl;

  return 0;
}

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll INF=1e18;
class edge
{
    public:
        int e,nxt;
		ll cap;
        edge(int e1=-1,int nxt1=-1,ll cap1=0)
        {
            e=e1,nxt=nxt1,cap=cap1;
        }
};
int S,T;
int dep[2510];
bool vis[2510];
class graph
{
    public:
        edge g[3000000];
        int head[2510],tmpcnt;
        int cur[2510];
        void init()
        {
            memset(head,255,sizeof(head));
            tmpcnt=0;
        }
        void addedge(int s,int e,ll cap)
        {
        	if(cap==0)return;
            g[tmpcnt]=edge(e,head[s],cap),head[s]=tmpcnt++;
            g[tmpcnt]=edge(s,head[e],0),head[e]=tmpcnt++;
        }
        bool bfs()
        {
            memset(vis,0,sizeof(vis));
            memset(dep,0,sizeof(dep));
            queue<int> q;
            q.push(S);
            vis[S]=1;
            while(!q.empty())
            {
                int fr=q.front();q.pop();
                for(int i=head[fr];i!=-1;i=g[i].nxt)
                {
                    if(g[i].cap>0&&!vis[g[i].e])
                    {
                        dep[g[i].e]=dep[fr]+1;
                        vis[g[i].e]=1;
                        q.push(g[i].e);
                    }
                }
            }
            return vis[T];
        }
        ll dfs(int np,ll maxflow)
        {
            ll f,flow=0;
            if(np==T||!maxflow)return maxflow;
            for(int i=cur[np];i!=-1;i=g[i].nxt)
            {
            	cur[np]=i;
                if(g[i].cap>0&&dep[g[i].e]==dep[np]+1&&(f=dfs(g[i].e,min(g[i].cap,maxflow)))>0)
                {
                    g[i].cap-=f;
                    g[i^1].cap+=f;
                    flow+=f;
                    maxflow-=f;
                    if(!maxflow)break;
                }
            }
            return flow;
        }
        ll dinic()
        {
            ll out=0;
            while(bfs())
				memcpy(cur,head,sizeof(cur)),out+=dfs(S,INF);
            return out;
        }
}G;
int n,m,dis[110][110],s,B,K;
ll vl[100010];
class ship
{
	public:
		int x,a,f,p;
}sp[100010];
vector<pair<int,int> > bas[110];
class dependency
{
	public:
		int s,e;
}dpd[1010];
int flag[1000010];
int main()
{
	scanf("%d%d",&n,&m);
	memset(dis,0x3f,sizeof(dis));
	for(int i=1;i<=n;i++)dis[i][i]=0;
	for(int i=1,ti,tj;i<=m;i++)
	{
		scanf("%d%d",&ti,&tj);
		dis[ti][tj]=dis[tj][ti]=min(dis[ti][tj],1);
	}
	for(int k=1;k<=n;k++)
		for(int i=1;i<=n;i++)
			for(int j=1;j<=n;j++)
				dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
	scanf("%d%d%d",&s,&B,&K);
	for(int i=1;i<=s;i++)
		scanf("%d%d%d%d",&sp[i].x,&sp[i].a,&sp[i].f,&sp[i].p);
	for(int i=1,ti,tj,tk;i<=B;i++)
	{
		scanf("%d%d%d",&ti,&tj,&tk);
		bas[ti].push_back(make_pair(tj,tk));
	}
	for(int i=1;i<=n;i++)
	{
		sort(bas[i].begin(),bas[i].end());
		reverse(bas[i].begin(),bas[i].end());
		vector<pair<int,int> > tmp;
		for(auto &x:bas[i])
		{
			while(!tmp.empty()&&x.second>=tmp.back().second)tmp.pop_back();
			tmp.push_back(x);
		}
		reverse(tmp.begin(),tmp.end());
		bas[i]=tmp;
	}
	for(int i=1;i<=K;i++)scanf("%d%d",&dpd[i].s,&dpd[i].e),flag[dpd[i].s]=flag[dpd[i].e]=1;
	for(int i=1;i<=s;i++)
	{
		int mxp=-1e9;
		for(int j=1;j<=n;j++)
		{
			if(dis[sp[i].x][j]<=sp[i].f)
			{
				auto x=upper_bound(bas[j].begin(),bas[j].end(),make_pair(sp[i].a+1,-1000000000));
				if(x==bas[j].begin())continue;
				x--;
				mxp=max(mxp,x->second);
			}
		}
		if(mxp==-1e9)vl[i]=-1e18;
		else vl[i]=mxp-sp[i].p;
	}
	vector<int> used;
	used.push_back(0);
	ll ans=0;
	for(int i=1;i<=s;i++)
	{
		if(!flag[i])
		{
			if(vl[i]>0)ans+=vl[i];
		}
		else flag[i]=used.size(),used.push_back(i);
	}
	int cnt=used.size();cnt--;
	S=cnt+1;T=cnt+2;
	G.init();
	for(int i=1;i<=cnt;i++)
	{
		if(vl[used[i]]>=0)G.addedge(S,i,vl[used[i]]),ans+=vl[used[i]];
		else G.addedge(i,T,-vl[used[i]]);
	}
	for(int i=1;i<=K;i++)
		G.addedge(flag[dpd[i].s],flag[dpd[i].e],INF);
	printf("%lld\n",ans-G.dinic());
	return 0;
}

#pragma GCC optimize ("O3")
#pragma GCC target ("sse4")

#include <bits/stdc++.h>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/rope>

using namespace std;
using namespace __gnu_pbds;
using namespace __gnu_cxx;

typedef long long ll;
typedef long double ld;
typedef complex<ld> cd;

typedef pair<int, int> pi;
typedef pair<ll,ll> pl;
typedef pair<ld,ld> pd;

typedef vector<int> vi;
typedef vector<ld> vd;
typedef vector<ll> vl;
typedef vector<pi> vpi;
typedef vector<pl> vpl;
typedef vector<cd> vcd;

template <class T> using Tree = tree<T, null_type, less<T>, rb_tree_tag,tree_order_statistics_node_update>;

#define FOR(i, a, b) for (int i = (a); i < (b); i++)
#define F0R(i, a) for (int i = 0; i < (a); i++)
#define FORd(i,a,b) for (int i = (b)-1; i >= (a); i--)
#define F0Rd(i,a) for (int i = (a)-1; i >= 0; i--)
#define trav(a, x) for (auto& a : x)

#define mp make_pair
#define pb push_back
#define f first
#define s second
#define lb lower_bound
#define ub upper_bound

#define sz(x) (int)x.size()
#define all(x) begin(x), end(x)
#define rsz resize

const int MOD = 1000000007; // 998244353
const ll INF = 1e18;
const int MX = 200005;
const ld PI = 4*atan((ld)1);

template<class T> void ckmin(T &a, T b) { a = min(a, b); }
template<class T> void ckmax(T &a, T b) { a = max(a, b); }

namespace input {
    template<class T> void re(complex<T>& x);
    template<class T1, class T2> void re(pair<T1,T2>& p);
    template<class T> void re(vector<T>& a);
    template<class T, size_t SZ> void re(array<T,SZ>& a);

    template<class T> void re(T& x) { cin >> x; }
    void re(double& x) { string t; re(t); x = stod(t); }
    void re(ld& x) { string t; re(t); x = stold(t); }
    template<class Arg, class... Args> void re(Arg& first, Args&... rest) {
        re(first); re(rest...);
    }

    template<class T> void re(complex<T>& x) { T a,b; re(a,b); x = cd(a,b); }
    template<class T1, class T2> void re(pair<T1,T2>& p) { re(p.f,p.s); }
    template<class T> void re(vector<T>& a) { F0R(i,sz(a)) re(a[i]); }
    template<class T, size_t SZ> void re(array<T,SZ>& a) { F0R(i,SZ) re(a[i]); }
}

using namespace input;

namespace output {
    template<class T1, class T2> void pr(const pair<T1,T2>& x);
    template<class T, size_t SZ> void pr(const array<T,SZ>& x);
    template<class T> void pr(const vector<T>& x);
    template<class T> void pr(const set<T>& x);
    template<class T1, class T2> void pr(const map<T1,T2>& x);

    template<class T> void pr(const T& x) { cout << x; }
    template<class Arg, class... Args> void pr(const Arg& first, const Args&... rest) {
        pr(first); pr(rest...);
    }

    template<class T1, class T2> void pr(const pair<T1,T2>& x) {
        pr("{",x.f,", ",x.s,"}");
    }
    template<class T> void prContain(const T& x) {
        pr("{");
        bool fst = 1; for (const auto& a: x) pr(!fst?", ":"",a), fst = 0; // const needed for vector<bool>
        pr("}");
    }
    template<class T, size_t SZ> void pr(const array<T,SZ>& x) { prContain(x); }
    template<class T> void pr(const vector<T>& x) { prContain(x); }
    template<class T> void pr(const set<T>& x) { prContain(x); }
    template<class T1, class T2> void pr(const map<T1,T2>& x) { prContain(x); }

    void ps() { pr("\n"); }
    template<class Arg> void ps(const Arg& first) {
        pr(first); ps(); // no space at end of line
    }
    template<class Arg, class... Args> void ps(const Arg& first, const Args&... rest) {
        pr(first," "); ps(rest...); // print w/ spaces
    }
}

using namespace output;

namespace io {
    void setIn(string s) { freopen(s.c_str(),"r",stdin); }
    void setOut(string s) { freopen(s.c_str(),"w",stdout); }
    void setIO(string s = "") {
        ios_base::sync_with_stdio(0); cin.tie(0); // fast I/O
        if (sz(s)) { setIn(s+".in"), setOut(s+".out"); } // for USACO
    }
}

using namespace io;

template<class T> T invGeneral(T a, T b) {
    a %= b; if (a == 0) return b == 1 ? 0 : -1;
    T x = invGeneral(b,a);
    return x == -1 ? -1 : ((1-(ll)b*x)/a+b)%b;
}

template<class T> struct modular {
    T val;
    explicit operator T() const { return val; }
    modular() { val = 0; }
    template<class U> modular(const U& v) {
        val = (-MOD <= v && v <= MOD) ? v : v % MOD;
        if (val < 0) val += MOD;
    }
    friend ostream& operator<<(ostream& os, const modular& a) { return os << a.val; }
    friend bool operator==(const modular& a, const modular& b) { return a.val == b.val; }
    friend bool operator!=(const modular& a, const modular& b) { return !(a == b); }

    modular operator-() const { return modular(-val); }
    modular& operator+=(const modular& m) { if ((val += m.val) >= MOD) val -= MOD; return *this; }
    modular& operator-=(const modular& m) { if ((val -= m.val) < 0) val += MOD; return *this; }
    modular& operator*=(const modular& m) { val = (ll)val*m.val%MOD; return *this; }
    friend modular exp(modular a, ll p) {
        modular ans = 1; for (; p; p /= 2, a *= a) if (p&1) ans *= a;
        return ans;
    }
    friend modular inv(const modular& a) {
        auto i = invGeneral(a.val,MOD); assert(i != -1);
        return i;
    } // equivalent to return exp(b,MOD-2) if MOD is prime
    modular& operator/=(const modular& m) { return (*this) *= inv(m); }

    friend modular operator+(modular a, const modular& b) { return a += b; }
    friend modular operator-(modular a, const modular& b) { return a -= b; }
    friend modular operator*(modular a, const modular& b) { return a *= b; }

    friend modular operator/(modular a, const modular& b) { return a /= b; }
};

typedef modular<int> mi;
typedef pair<mi,mi> pmi;
typedef vector<mi> vmi;
typedef vector<pmi> vpmi;

template<int SZ> struct Dinic {
    struct Edge { int v, rev; ll flow, cap; };

    vector<Edge> adj[SZ];

    void addEdge(int u, int v, ll cap) {
        assert(cap >= 0); // don't do smth dumb
        Edge a{v, sz(adj[v]), 0, cap}, b{u, sz(adj[u]), 0, 0};
        adj[u].pb(a), adj[v].pb(b);
    }

    int ST, EN, level[SZ], ind[SZ];

    bool bfs() { // level = shortest distance from source
        // after computing flow, edges {u,v} such that level[u] \neq -1, level[v] = -1 are part of min cut
        F0R(i,SZ) level[i] = -1, ind[i] = 0;
        level[ST] = 0;
        queue<int> q; q.push(ST);
        while (sz(q)) {
            int u = q.front(); q.pop();
            trav(e,adj[u]) if (level[e.v] < 0 && e.flow < e.cap) {
                level[e.v] = level[u] + 1;
                q.push(e.v);
            }
        }
        return level[EN] >= 0;
    }

    ll sendFlow(int s, ll flow) {
        if (s == EN) return flow;
        for (  ; ind[s] < sz(adj[s]); ind[s] ++) {
            Edge& e = adj[s][ind[s]];
            if (level[e.v] != level[s]+1 || e.flow == e.cap) continue;
            ll f = sendFlow(e.v, min(flow, e.cap-e.flow));
            if (f) { // saturated at least one edge
                e.flow += f; adj[e.v][e.rev].flow -= f;
                return f;
            }
        }
        return 0;
    }

    ll maxFlow(int _ST, int _EN) {
        ST = _ST, EN = _EN; if (ST == EN) return -1;
        ll tot = 0;
        while (bfs()) while (auto flow = sendFlow(ST, LLONG_MAX)) tot += flow;
        return tot;
    }
};

Dinic<100002> D;
int n,m,dist[101][101];
ll cur[101];

int main() {
    setIO(); re(n,m);
    FOR(i,1,n+1) {
        FOR(j,1,n+1) if (i != j) dist[i][j] = MOD;
    }
    F0R(i,m) {
        int u,v; re(u,v);
        ckmin(dist[u][v],1);
        ckmin(dist[v][u],1);
    }
    FOR(k,1,n+1) FOR(i,1,n+1) FOR(j,1,n+1) ckmin(dist[i][j],dist[i][k]+dist[k][j]);

    int s,b,k; re(s,b,k);
    vector<array<int,5>> S(s);
    vector<array<int,3>> B(b);
    F0R(i,s) {
        F0R(j,4) re(S[i][j]);
        S[i][4] = i+1;
    }
    re(B);
    trav(t,S) swap(t[1],t[0]);
    trav(t,B) swap(t[1],t[0]);
    sort(all(S)), sort(all(B));
    int ind = 0; ll ans = 0;
    FOR(i,1,n+1) cur[i] = -INF;
    trav(t,S) {
        while (ind < sz(B) && B[ind][0] <= t[0]) {
            ckmax(cur[B[ind][1]],(ll)B[ind][2]);
            ind ++;
        }
        ll res = -INF;
        FOR(i,1,n+1) if (dist[t[1]][i] <= t[2]) ckmax(res,cur[i]);
        if (res != -INF) res -= t[3];
        if (res < 0) D.addEdge(t[4],s+1,-res);
        else {
            D.addEdge(0,t[4],res);
            ans += res;
        }
    }
    F0R(i,k) {
        int s1,s2; re(s1,s2);
        D.addEdge(s1,s2,INF);
    }
    ps(ans-D.maxFlow(0,s+1));
}

/* stuff you should look for
    * int overflow, array bounds
    * special cases (n=1?), set tle
    * do smth instead of nothing and stay organized
*/

#include <bits/stdc++.h>
using namespace std;

#define rep(i, a, b) for(int i = a; i < (b); ++i)
#define trav(a, x) for(auto& a : x)
#define all(x) x.begin(), x.end()
#define sz(x) (int)(x).size()
typedef long long ll;
typedef pair<int, int> pii;
typedef vector<int> vi;

typedef ll Flow;
struct Edge {
	int dest, back;
	Flow f, c;
};

struct PushRelabel {
	vector<vector<Edge>> g;
	vector<Flow> ec;
	vector<Edge*> cur;
	vector<vi> hs; vi H;
	PushRelabel(int n) : g(n), ec(n), cur(n), hs(2*n), H(n) {}

	void add_edge(int s, int t, Flow cap, Flow rcap=0) {
		if (s == t) return;
		Edge a = {t, sz(g[t]), 0, cap};
		Edge b = {s, sz(g[s]), 0, rcap};
		g[s].push_back(a);
		g[t].push_back(b);
	}

	void add_flow(Edge& e, Flow f) {
		Edge &back = g[e.dest][e.back];
		if (!ec[e.dest] && f) hs[H[e.dest]].push_back(e.dest);
		e.f += f; e.c -= f; ec[e.dest] += f;
		back.f -= f; back.c += f; ec[back.dest] -= f;
	}
	Flow maxflow(int s, int t) {
		int v = sz(g); H[s] = v; ec[t] = 1;
		vi co(2*v); co[0] = v-1;
		rep(i,0,v) cur[i] = g[i].data();
		trav(e, g[s]) add_flow(e, e.c);

		for (int hi = 0;;) {
			while (hs[hi].empty()) if (!hi--) return -ec[s];
			int u = hs[hi].back(); hs[hi].pop_back();
			while (ec[u] > 0)  // discharge u
				if (cur[u] == g[u].data() + sz(g[u])) {
					H[u] = 1e9;
					trav(e, g[u]) if (e.c && H[u] > H[e.dest]+1)
						H[u] = H[e.dest]+1, cur[u] = &e;
					if (++co[H[u]], !--co[hi] && hi < v)
						rep(i,0,v) if (hi < H[i] && H[i] < v)
							--co[H[i]], H[i] = v + 1;
					hi = H[u];
				} else if (cur[u]->c && H[u] == H[cur[u]->dest]+1)
					add_flow(*cur[u], min(ec[u], cur[u]->c));
				else ++cur[u];
		}
	}
};

vi val, comp, z, cont;
int Time, ncomps;
template<class G, class F> int dfs(int j, G& g, F f) {
	int low = val[j] = ++Time, x; z.push_back(j);
	trav(e,g[j]) if (comp[e] < 0)
		low = min(low, val[e] ?: dfs(e,g,f));

	if (low == val[j]) {
		do {
			x = z.back(); z.pop_back();
			comp[x] = ncomps;
			cont.push_back(x);
		} while (x != j);
		f(cont); cont.clear();
		ncomps++;
	}
	return val[j] = low;
}
template<class G, class F> void scc(G& g, F f) {
	int n = sz(g);
	val.assign(n, 0); comp.assign(n, -1);
	Time = ncomps = 0;
	rep(i,0,n) if (comp[i] < 0) dfs(i, g, f);
}

vector<int> which;
int qq = 0;

void do_stuff(vector<int> x){
	for(int a : x){
		which[a] = qq;
	}
	qq += 1;
}

void solve2(int n, vector<ll> cost, vector<pair<int,int> > dep){
	vector<bool> has_edge(n, false);
	ll ans = 0;
	for(auto r : dep){
		has_edge[r.first] = has_edge[r.second] = true;
	}
	vector<int> vlist;
	map<int,int> zmap;
	vector<ll> newcost;
	for(int i = 0; i < n; i++){
		if(!has_edge[i]){
			if(cost[i] >= 0) ans += cost[i];
		} else {
			zmap[i] = (int)vlist.size();
			vlist.push_back(i);
			newcost.push_back(cost[i]);
		}
	}
	for(auto& r : dep){
		r.first = zmap[r.first];
		r.second = zmap[r.second];
	}

	cost = newcost;

	n = vlist.size();

	PushRelabel flow(n+2);
	for(int i = 0; i < n; i++){
		if(cost[i] >= 0){
			flow.add_edge(n, i, cost[i]);
			ans += cost[i];
		} else {
			flow.add_edge(i, n+1, -cost[i]);
		}
	}
	for(auto r : dep){
		flow.add_edge(r.first, r.second, 1e18);
	}
	ans -= flow.maxflow(n, n+1);
	cout << ans << '\n';
}

void solve(int n, vector<ll> cost, vector<pair<int,int> > dep){
	which.resize(n);
	vector<vector<int> > edges(n);
	for(auto r : dep){
		edges[r.first].push_back(r.second);
	}
	scc(edges, do_stuff);
	vector<pair<int,int> > new_dep;

	vector<ll> new_cost(qq, 0);
	for(int i = 0; i < n; i++){
		new_cost[which[i]] += cost[i];
	}
	for(auto r : dep){
		if(which[r.first] == which[r.second]) continue;
		new_dep.emplace_back(which[r.first], which[r.second]);
	}
	solve2(qq, new_cost, new_dep);
}

using ll = long long;

int main(){
	ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	int n, m;
	cin >> n >> m;
	vector<vector<int> > edges(n);
	vector<vector<int> > dist(n, vector<int>(n, 1e9));
	for(int i = 0; i < n; i++) dist[i][i] = 0;
	for(int i = 0; i < m; i++){
		int u, v;
		cin >> u >> v;
		u--; v--;
		dist[u][v] = min(dist[u][v], 1);
		dist[v][u] = min(dist[v][u], 1);
	}
	for(int _ = 0; _ < 3; _++)
	for(int k = 0; k < n; k++){
		for(int i = 0; i < n; i++){
			for(int j = 0; j < n; j++){
				dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
			}
		}
	}
	int s, b, k;
	cin >> s >> b >> k;
	vector<int> x1(s), a(s), f(s), p(s);
	vector<int> x2(b), d(b), g(b);
	for(int i = 0; i < s; i++){
		cin >> x1[i] >> a[i] >> f[i] >> p[i];
		x1[i]--;
	}
	for(int i = 0; i < b; i++){
		cin >> x2[i] >> d[i] >> g[i];
		x2[i]--;
	}
	vector<ll> cost(s, 0);

	vector<vector<pair<int,ll> > > contents(n);

	for(int i = 0; i < b; i++){
		contents[x2[i]].emplace_back(d[i], g[i]);
	}
	for(int i = 0; i < n; i++){
		sort(contents[i].begin(), contents[i].end());
		int best = 0;
		vector<pair<int,ll> > rc;
		rc.emplace_back(0, -1e15);
		for(pair<int,ll> xx : contents[i]){
			if(xx.second <= best) continue;
			best = xx.second;
			rc.push_back(xx);
		}
		contents[i] = rc;
	}

	for(int i = 0; i < s; i++){
		ll best_base = -1e15;
		for(int v = 0; v < n; v++){
			if(f[i] >= dist[x1[i]][v]){
				// find best j with d[j] <= a[i]
				int ss = 0;
				int ee = contents[v].size();
				while(ss + 1 < ee){
					int mm = (ss + ee) / 2;
					if(contents[v][mm].first <= a[i]){
						ss = mm;
					} else {
						ee = mm;
					}
				}
				best_base = max(best_base, contents[v][ss].second);
			}
		}
		cost[i] = best_base - p[i];
	}

	vector<pair<int,int> > dep;
	for(int i = 0; i < k; i++){
		int u, v;
		cin >> u >> v;
		u--; v--;
		dep.emplace_back(u, v);
	}
	solve(s, cost, dep);
}

#include <bits/stdc++.h>
#define N 107
#define M 100007
#define INF 100000000000007LL
#define E 1000007
using namespace std;
int n, m, d[N][N], s, b, k;
struct spaceship { int x, a, f, p; } sp[M];
struct base { int x, d, g; } ba[M];
vector<int> v[N];
bool cmp(int x, int y) { return ba[x].d < ba[y].d; }
vector<pair<int, int> > u[N];
long long val[M];
int e, head[M], nxt[E], to[E], op[E];
long long cap[E];
void add_edge(int x, int y, long long c) {
    nxt[++ e] = head[x], to[head[x] = e] = y;
    cap[e] = c, op[e] = e + 1;
    nxt[++ e] = head[y], to[head[y] = e] = x;
    cap[e] = 0, op[e] = e - 1;
}
int S, T, nodes, dis[M], cnt[M];
long long sap(int x, long long delta) {
    if(x == T) return delta;
    long long sum = 0;
    int mindis = nodes;
    for(int i = head[x]; i; i = nxt[i]) {
        if(cap[i] && dis[x] == dis[to[i]] + 1) {
            long long save = sap(to[i], min(cap[i], delta - sum));
            sum += save, cap[i] -= save, cap[op[i]] += save;
            if(dis[S] >= nodes || sum == delta) return sum;
        }
        if(cap[i]) mindis = min(mindis, dis[to[i]]);
    }
    if(!sum)
        if(! -- cnt[dis[x]]) dis[S] = nodes;
        else ++ cnt[dis[x] = mindis + 1];
    return sum;
}
long long max_flow() {
    long long res = 0;
    while(dis[S] < nodes) res += sap(S, INF);
    return res;
}
int main() {
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; ++ i)
        for(int j = 1; j <= n; ++ j) if(i != j) d[i][j] = N;
    for(int i = 1, x, y; i <= m; ++ i) {
        scanf("%d%d", &x, &y);
        if(x == y) continue;
        d[x][y] = d[y][x] = 1;
    }
    for(int t = 1; t <= n; ++ t)
        for(int i = 1; i <= n; ++ i) if(i != t)
            for(int j = 1; j <= n; ++ j) if(j != t && j != i) d[i][j] = min(d[i][j], d[i][t] + d[t][j]);
    scanf("%d%d%d", &s, &b, &k);
    for(int i = 1; i <= s; ++ i) scanf("%d%d%d%d", &sp[i].x, &sp[i].a, &sp[i].f, &sp[i].p);
    for(int i = 1; i <= b; ++ i) {
        scanf("%d%d%d", &ba[i].x, &ba[i].d, &ba[i].g);
        v[ba[i].x].push_back(i);
    }
    for(int i = 1; i <= n; ++ i) {
        sort(v[i].begin(), v[i].end(), cmp);
        int mx = 0;
        for(int j: v[i]) {
            mx = max(mx, ba[j].g);
            u[i].push_back(make_pair(ba[j].d, mx));
        }
    }
    for(int i = 1; i <= s; ++ i) {
        val[i] = -INF;
        for(int j = 1; j <= n; ++ j) if(d[sp[i].x][j] < N && d[sp[i].x][j] <= sp[i].f) {
            int t = -1, l = 0, r = u[j].size() - 1;
            while(l <= r) {
                int mid = (l + r) >> 1;
                if(u[j][mid].first <= sp[i].a) t = mid, l = mid + 1;
                else r = mid - 1;
            }
            if(t != -1) val[i] = max(val[i], 1LL * u[j][t].second - sp[i].p);
        }
    }
    S = 0, T = s + 1, nodes = s + 2;
    long long ans = 0;
    for(int i = 1; i <= s; ++ i)
        if(val[i] > 0) ans += val[i], add_edge(S, i, val[i]);
        else if(val[i] < 0) add_edge(i, T, -val[i]);
    for(int i = 1, x, y; i <= k; ++ i) scanf("%d%d", &x, &y), add_edge(x, y, INF);
    ans -= max_flow();
    cout << ans << endl;
}

#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;
int dis[110][110], nV, nE, n, m;
#define N_ 220100
#define M_ 221000
#define pii pair<int,int>
struct MaxFlow {
	vector<int>G[N_];
	struct Edge {
		int b, e;
		long long f;
	}E[M_];
	int EC, PV[N_], Q[N_], Level[N_], n, source, sink;
	long long flow, INF = 1e16;
	void init(int N, int S, int T) {
		source = S, sink = T, flow = EC = 0;
		n = N;
		for (int i = 0; i <= n; i++)G[i].clear();
	}
	void Add_Edge(int a, int b, long long f) {
		G[a].push_back(EC);
		G[b].push_back(EC + 1);
		E[EC++] = { a,b,f };
		E[EC++] = { b,a,0 };
	}
	long long BlockFlow(int a, long long f) {
		if (a == sink)return f;
		for (int &i = PV[a]; i >= 0; i--) {
			int t = G[a][i];
			if (E[t].f && Level[E[t].e] == Level[a] + 1) {
				long long ff = BlockFlow(E[t].e, min(E[t].f, f));
				if (ff) {
					E[t].f -= ff;
					E[t ^ 1].f += ff;
					return ff;
				}
			}
		}
		return 0ll;
	}
	bool GetLevel() {
		int head = 0, tail = 0, i;
		for (i = 1; i <= n; i++)Level[i] = -1;
		Q[++tail] = source; Level[source] = 0;
		while (head < tail) {
			int x = Q[++head];
			for (auto &t : G[x]) {
				if (E[t].f && Level[E[t].e] == -1) {
					Level[E[t].e] = Level[x] + 1;
					Q[++tail] = E[t].e;
				}
			}
		}
		return Level[sink] != -1;
	}
	void Dinic() {
		int i;
		long long t;
		flow = 0;
		while (GetLevel()) {
			for (i = 1; i <= n; i++)PV[i] = G[i].size() - 1;
			while (t = BlockFlow(source, INF)) {
				flow += t;
			}
		}
	}
}G1;
struct AA {
	int x, a, f, cost;
}A[110000];
struct BB {
	int d, k;
	bool operator < (const BB &p)const {
		return d < p.d;
	}
};
vector<BB>U[110];
vector<int>MX[110];
pii Ed[1010];
int K, chk[101000];
long long WW[101000];
int main() {
	int i, j, k;
	scanf("%d%d", &nV, &nE);
	for (i = 1; i <= nV; i++)for (j = 1; j <= nV; j++)if (i != j)dis[i][j] = 1e9;
	for (i = 0; i < nE; i++) {
		int a, b;
		scanf("%d%d", &a, &b);
		dis[a][b] = dis[b][a] = 1;
	}
	for (k = 1; k <= nV; k++)for (i = 1; i <= nV; i++)for (j = 1; j <= nV; j++)dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]);
	scanf("%d%d%d", &n, &m, &K);
	for (i = 1; i <= n; i++) {
		scanf("%d%d%d%d", &A[i].x, &A[i].a, &A[i].f, &A[i].cost);
	}
	for (i = 1; i <= m; i++) {
		int x, d, k;
		scanf("%d%d%d", &x, &d, &k);
		U[x].push_back({ d,k });
	}
	for (i = 1; i <= nV; i++) {
		int sz = U[i].size();
		if (!sz)continue;
		MX[i].resize(sz);
		sort(U[i].begin(), U[i].end());
		for (j = 0; j < sz; j++) {
			MX[i][j] = U[i][j].k;
			if (j)MX[i][j] = max(MX[i][j], MX[i][j - 1]);
		}
	}
	for (i = 1; i <= n; i++) {
		long long z = -1e16;
		for (j = 1; j <= nV; j++) {
			if (U[j].empty() || A[i].f < dis[A[i].x][j])continue;
			BB tp = { A[i].a + 1,0 };
			int pv = lower_bound(U[j].begin(), U[j].end(), tp) - U[j].begin();
			if (!pv)continue;
			z = max(z, 0ll + MX[j][pv - 1] - A[i].cost);
		}
		WW[i] = z;
	}
	for (i = 0; i < K; i++) {
		int a, b;
		scanf("%d%d", &a, &b);
		Ed[i] = { a,b };
		chk[a] = chk[b] = 1;
	}
	long long sum = 0;
	G1.init(n + 2, n + 1, n + 2);
	long long BS = 1e10, tt = 0;
	for (i = 1; i <= n; i++) {
		if (!chk[i]) {
			sum += max(WW[i], 0ll);
		}
		else {
			tt += BS;
			G1.Add_Edge(G1.source, i, BS);
			G1.Add_Edge(i, G1.sink, BS - WW[i]);
		}
	}
	for (i = 0; i < K; i++) {
		G1.Add_Edge(Ed[i].first, Ed[i].second, G1.INF);
	}
	G1.Dinic();
	printf("%lld\n", sum + tt - G1.flow);
}

#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <utility>
#include <limits>

struct base_t {
    int64_t position, defense, gold;
    friend std::istream& operator >> (std::istream& flux, base_t& b) {
        flux >> b.position >> b.defense >> b.gold;
        return flux;
    }
    bool operator < (const base_t& b) const {
        return this->defense < b.defense;
    }
};

struct ship_t {
    int64_t position, strength, fuel, price;
    friend std::istream& operator >> (std::istream& flux, ship_t& s) {
        flux >> s.position >> s.strength >> s.fuel >> s.price;
        return flux;
    }
};

struct Flow_Edge {
    int from, to;
    int64_t capacity, flow = 0LL;
    Flow_Edge (const int& from, const int& to, const int64_t& capacity): from (from), to (to), capacity (capacity) {
    }
};

constexpr int64_t Inf = 1e12 + 42;
using Ip = std::pair <int64_t, int64_t>;
using Vi = std::vector <int>;
using VVi = std::vector <Vi>;
using Vi64 = std::vector <int64_t>;
using VVi64 = std::vector <Vi64>;
using VIp = std::vector <Ip>;
using VVIp = std::vector <VIp>;
using Vf = std::vector <Flow_Edge>;
using Vs = std::vector <ship_t>;
using Vb = std::vector <base_t>;
using Qi = std::queue <int>;

struct Dinic {
    Vf Edges;
    VVi Adj;
    int n, s, t;
    Vi Level, Ptr;
    Qi Q;
    Dinic (const int& n, const int& s, const int& t): n (n), s (s), t (t) {
        Adj.resize (n), Level.resize (n), Ptr.resize (n);
    }
    void add_edge (const int& u, const int& v, const int64_t& cap) {
        if (u == v) return;
        Edges.emplace_back (Flow_Edge (u, v, cap));
        Adj[u].emplace_back (Edges.size () - 1);
        Edges.emplace_back (Flow_Edge (v, u, 0));
        Adj[v].emplace_back (Edges.size () - 1);
    }
    bool bfs () {
        while (!Q.empty ()) {
            int v = Q.front (); Q.pop ();
            for (const auto& id: Adj[v]) {
                if (Edges[id].capacity - Edges[id].flow < 1)
                    continue;
                if (Level[Edges[id].to] != -1)
                    continue;
                Level[Edges[id].to] = Level[v] + 1;
                Q.push (Edges[id].to);
            }
        }
        return Level[t] != -1;
    }
    int64_t dfs (const int& v, const int64_t& pushed) {
        if (!pushed)
            return 0LL;
        if (v == t)
            return pushed;
        for (int& cid = Ptr[v]; cid < (int)Adj[v].size (); ++ cid) {
            int id = Adj[v][cid], u = Edges[id].to;
            if (Level[v] + 1 != Level[u] || Edges[id].capacity - Edges[id].flow < 1)
                continue;
            int64_t transport = dfs (u, std::min (pushed, Edges[id].capacity - Edges[id].flow));
            if (!transport)
                continue;
            Edges[id].flow += transport;
            Edges[id ^ 1].flow -= transport;
            return transport;
        }
        return 0LL;
    }
    int64_t max_flow () {
        int64_t f = 0LL;
        while (true) {
            std::fill (Level.begin (), Level.end (), -1);
            Level[s] = 0;
            Q.push (s);
            if (!bfs ())
                break;
            std::fill (Ptr.begin (), Ptr.end (), 0);
            while (int64_t pushed = dfs (s, Inf))
                f += pushed;
        }
        return f;
    }
};

int n, m, u, v, s, b, k;
Vi64 Value;
VVi64 Cost;
Vs Ships;
Vb Bases;
VVIp Bases_at;

int main () {
    std::ios_base::sync_with_stdio (false), std::cin.tie (nullptr), std::cout.tie (nullptr);
    std::cin >> n >> m;
    Cost.assign (n + 1, Vi64 (n + 1, Inf));
    for (int i = 1; i <= n; ++ i) Cost[i][i] = 0LL;
    for (int i = 1; i <= m; ++ i)
        std::cin >> u >> v, Cost[u][v] = Cost[v][u] = std::min (Cost[u][v], 1LL);

    for (int k = 1; k <= n; ++ k)
        for (int i = 1; i <= n; ++ i)
            for (int j = 1; j <= n; ++ j)
                Cost[i][j] = std::min (Cost[i][j], Cost[i][k] + Cost[k][j]);

    std::cin >> s >> b >> k;
    Value.resize (s + 1), Bases_at.resize (n + 1);
    Ships.resize (s + 1), Bases.resize (b + 1);
    for (int i = 1; i <= s; ++ i)
        std::cin >> Ships[i];
    for (int i = 1; i <= b; ++ i)
        std::cin >> Bases[i];

    std::sort (Bases.begin (), Bases.end ());
    for (int i = 1; i <= b; ++ i) {
        int pos = Bases[i].position;
        if (Bases_at[pos].empty () || Bases_at[pos].back ().second < Bases[i].gold)
            Bases_at[pos].emplace_back (std::make_pair (Bases[i].defense, Bases[i].gold));
    }

    int source = 0, sink = s + 1;
    Dinic dinic (s + 2, source, sink);
    int64_t ans = 0LL;
    for (int i = 1; i <= s; ++ i) {
        bool found = false;
        for (int p = 1; p <= n; ++ p) {
            if (Cost[Ships[i].position][p] > Ships[i].fuel)
                continue;
            auto it = std::upper_bound (Bases_at[p].begin (), Bases_at[p].end (), std::make_pair (Ships[i].strength, Inf));
            if (it != Bases_at[p].begin ())
                -- it, found = true, Value[i] = std::max (Value[i], it->second);
        }
        Value[i] -= Ships[i].price;
        if (!found)
            Value[i] = -Inf;
        if (Value[i] >= 0)
            ans += Value[i], dinic.add_edge (source, i, Value[i]);
        else
            dinic.add_edge (i, sink, -Value[i]);
    }

    for (int i = 1; i <= k; ++ i)
        std::cin >> u >> v,
        dinic.add_edge (u, v, Inf);

    std::cout << ans - dinic.max_flow ();

    return 0;
}

#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <utility>
#include <limits>

struct base_t {
    int64_t position, defense, gold;
    friend std::istream& operator >> (std::istream& flux, base_t& b) {
        flux >> b.position >> b.defense >> b.gold;
        return flux;
    }
    bool operator < (const base_t& b) const {
        //if (this->defense != b.defense)
            return this->defense < b.defense;
        //return this->gold < b.gold;
    }
};

struct ship_t {
    int64_t position, strength, fuel, price;
    friend std::istream& operator >> (std::istream& flux, ship_t& s) {
        flux >> s.position >> s.strength >> s.fuel >> s.price;
        return flux;
    }
};

struct Flow_Edge {
    int from, to;
    int64_t capacity, flow = 0LL;
    Flow_Edge (const int& from, const int& to, const int64_t& capacity): from (from), to (to), capacity (capacity) {
    }
};

constexpr int64_t Inf = 1e12 + 42;
using Ip = std::pair <int64_t, int64_t>;
using Vi = std::vector <int>;
using VVi = std::vector <Vi>;
using Vi64 = std::vector <int64_t>;
using VVi64 = std::vector <Vi64>;
using VIp = std::vector <Ip>;
using VVIp = std::vector <VIp>;
using Vf = std::vector <Flow_Edge>;
using Vs = std::vector <ship_t>;
using Vb = std::vector <base_t>;
using Qi = std::queue <int>;

struct Dinic {
    Vf Edges;
    VVi Adj;
    int n, s, t;
    Vi Level, Ptr;
    Qi Q;
    Dinic (const int& n, const int& s, const int& t): n (n), s (s), t (t) {
        Adj.resize (n), Level.resize (n), Ptr.resize (n);
    }
    void add_edge (const int& u, const int& v, const int64_t& cap) {
        if (u == v) return;
        Edges.emplace_back (Flow_Edge (u, v, cap));
        Adj[u].emplace_back (Edges.size () - 1);
        Edges.emplace_back (Flow_Edge (v, u, 0));
        Adj[v].emplace_back (Edges.size () - 1);
    }
    bool bfs () {
        while (!Q.empty ()) {
            int v = Q.front (); Q.pop ();
            for (const auto& id: Adj[v]) {
                if (Edges[id].capacity - Edges[id].flow < 1)
                    continue;
                if (Level[Edges[id].to] != -1)
                    continue;
                Level[Edges[id].to] = Level[v] + 1;
                Q.push (Edges[id].to);
            }
        }
        return Level[t] != -1;
    }
    int64_t dfs (const int& v, const int64_t& pushed) {
        if (!pushed)
            return 0LL;
        if (v == t)
            return pushed;
        for (int& cid = Ptr[v]; cid < (int)Adj[v].size (); ++ cid) {
            int id = Adj[v][cid], u = Edges[id].to;
            if (Level[v] + 1 != Level[u] || Edges[id].capacity - Edges[id].flow < 1)
                continue;
            int64_t transport = dfs (u, std::min (pushed, Edges[id].capacity - Edges[id].flow));
            if (!transport)
                continue;
            Edges[id].flow += transport;
            Edges[id ^ 1].flow -= transport;
            return transport;
        }
        return 0LL;
    }
    int64_t max_flow () {
        int64_t f = 0LL;
        while (true) {
            std::fill (Level.begin (), Level.end (), -1);
            Level[s] = 0;
            Q.push (s);
            if (!bfs ())
                break;
            std::fill (Ptr.begin (), Ptr.end (), 0);
            while (int64_t pushed = dfs (s, Inf))
                f += pushed;
        }
        return f;
    }
};

constexpr int N = 1e2 + 10, S = 1e5 + 10;
int n, m, u, v, s, b, k;
/*Vi64 Value;
VVi64 Cost;
Vs Ships;
Vb Bases;
VVIp Bases_at;*/
int64_t Value[S], Cost[N][N];
VIp Bases_at[N];
base_t Bases[S];
ship_t Ships[S];

int main () {
    std::cin >> n >> m;
    //Cost.assign (n + 1, Vi64 (n + 1, Inf));
    for (int i = 1; i <= n; ++ i)
        for (int j = i + 1; j <= n; ++ j) Cost[i][j] = Cost[j][i] = Inf;
    //for (int i = 1; i <= n; ++ i) Cost[i][i] = 0LL;
    for (int i = 1; i <= m; ++ i)
        std::cin >> u >> v, Cost[u][v] = Cost[v][u] = std::min (Cost[u][v], 1LL);

    for (int k = 1; k <= n; ++ k)
        for (int i = 1; i <= n; ++ i)
            for (int j = 1; j <= n; ++ j)
                Cost[i][j] = std::min (Cost[i][j], Cost[i][k] + Cost[k][j]);

    std::cin >> s >> b >> k;
    //Value.resize (s + 1), Bases_at.resize (n + 1);
    //Ships.resize (s + 1), Bases.resize (b + 1);
    for (int i = 1; i <= s; ++ i)
        std::cin >> Ships[i];
    for (int i = 1; i <= b; ++ i)
        std::cin >> Bases[i];

    std::sort (Bases + 1, Bases + b + 1);
    for (int i = 1; i <= b; ++ i) {
        int pos = Bases[i].position;
        if (Bases_at[pos].empty () || Bases_at[pos].back ().second < Bases[i].gold)
            Bases_at[pos].emplace_back (std::make_pair (Bases[i].defense, Bases[i].gold));
    }

    int source = 0, sink = s + 1;
    Dinic dinic (s + 2, source, sink);
    int64_t ans = 0LL;
    for (int i = 1; i <= s; ++ i) {
        bool found = false;
        for (int p = 1; p <= n; ++ p) {
            if (Cost[Ships[i].position][p] > Ships[i].fuel)
                continue;
            auto it = std::upper_bound (Bases_at[p].begin (), Bases_at[p].end (), std::make_pair (Ships[i].strength, Inf));
            if (it != Bases_at[p].begin ())
                -- it, found = true, Value[i] = std::max (Value[i], it->second);
        }
        Value[i] -= Ships[i].price;
        if (!found)
            Value[i] = -Inf;
        if (Value[i] >= 0)
            ans += Value[i], dinic.add_edge (source, i, Value[i]);
        else
            dinic.add_edge (i, sink, -Value[i]);
    }

    for (int i = 1; i <= k; ++ i)
        std::cin >> u >> v,
        dinic.add_edge (u, v, Inf);

    std::cout << ans - dinic.max_flow ();

    return 0;
}

#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <utility>
#include <limits>

struct base_t {
    int64_t position, defense, gold;
    friend std::istream& operator >> (std::istream& flux, base_t& b) {
        flux >> b.position >> b.defense >> b.gold;
        return flux;
    }
    bool operator < (const base_t& b) const {
        return this->defense < b.defense;
    }
};

struct ship_t {
    int64_t position, strength, fuel, price;
    friend std::istream& operator >> (std::istream& flux, ship_t& s) {
        flux >> s.position >> s.strength >> s.fuel >> s.price;
        return flux;
    }
};

struct Flow_Edge {
    int from, to;
    int64_t capacity, flow = 0LL;
    Flow_Edge (const int& from, const int& to, const int64_t& capacity): from (from), to (to), capacity (capacity) {
    }
};

constexpr auto Inf = std::numeric_limits <int64_t>::max () >> 1LL;
using Ip = std::pair <int64_t, int64_t>;
using Vi = std::vector <int>;
using VVi = std::vector <Vi>;
using Vi64 = std::vector <int64_t>;
using VVi64 = std::vector <Vi64>;
using VIp = std::vector <Ip>;
using VVIp = std::vector <VIp>;
using Vf = std::vector <Flow_Edge>;
using Vs = std::vector <ship_t>;
using Vb = std::vector <base_t>;
using Qi = std::queue <int>;

struct Dinic {
    Vf Edges;
    VVi Adj;
    int n, s, t;
    Vi Level, Ptr;
    Qi Q;
    Dinic (const int& n, const int& s, const int& t): n (n), s (s), t (t) {
        Adj.resize (n), Level.resize (n), Ptr.resize (n);
    }
    void add_edge (const int& u, const int& v, const int64_t& cap) {
        if (u == v) return;
        Edges.emplace_back (u, v, cap);
        Adj[u].emplace_back (Edges.size () - 1);
        Edges.emplace_back (v, u, 0);
        Adj[v].emplace_back (Edges.size () - 1);
    }
    bool bfs () {
        while (!Q.empty ()) {
            int v = Q.front (); Q.pop ();
            for (const auto& id: Adj[v]) {
                if (Edges[id].capacity - Edges[id].flow < 1)
                    continue;
                if (Level[Edges[id].to] != -1)
                    continue;
                Level[Edges[id].to] = Level[v] + 1;
                Q.push (Edges[id].to);
            }
        }
        return Level[t] != -1;
    }
    int64_t dfs (const int& v, const int64_t& pushed) {
        if (!pushed)
            return 0LL;
        if (v == t)
            return pushed;
        for (int& cid = Ptr[v]; cid < (int)Adj[v].size (); ++ cid) {
            int id = Adj[v][cid], u = Edges[id].to;
            if (Level[v] + 1 != Level[u] || Edges[id].capacity - Edges[id].flow < 1)
                continue;
            int64_t transport = dfs (u, std::min (pushed, Edges[id].capacity - Edges[id].flow));
            if (!transport)
                continue;
            Edges[id].flow += transport;
            Edges[id ^ 1].flow -= transport;
            return transport;
        }
        return 0LL;
    }
    int64_t max_flow () {
        int64_t f = 0LL;
        while (true) {
            std::fill (Level.begin (), Level.end (), -1);
            Level[s] = 0;
            Q.push (s);
            if (!bfs ())
                break;
            std::fill (Ptr.begin (), Ptr.end (), 0);
            while (int64_t pushed = dfs (s, Inf))
                f += pushed;
        }
        return f;
    }
};

int n, m, u, v, s, b, k;
Vi64 Value;
VVi64 Cost;
Vs Ships;
Vb Bases;
VVIp Bases_at;

int main () {
    std::ios_base::sync_with_stdio (false), std::cin.tie (nullptr), std::cout.tie (nullptr);
    std::cin >> n >> m;
    Cost.assign (n + 1, Vi64 (n + 1, Inf));
    for (int i = 1; i <= n; ++ i) Cost[i][i] = 0LL;
    for (int i = 1; i <= m; ++ i)
        std::cin >> u >> v, Cost[u][v] = Cost[v][u] = std::min (Cost[u][v], 1LL);

    for (int k = 1; k <= n; ++ k)
        for (int i = 1; i <= n; ++ i)
            for (int j = 1; j <= n; ++ j)
                Cost[i][j] = std::min (Cost[i][j], Cost[i][k] + Cost[k][j]);

    std::cin >> s >> b >> k;
    Value.resize (s + 1), Bases_at.resize (n + 1);
    Ships.resize (s + 1), Bases.resize (b + 1);
    for (int i = 1; i <= s; ++ i)
        std::cin >> Ships[i];
    for (int i = 1; i <= b; ++ i)
        std::cin >> Bases[i];

    std::sort (Bases.begin (), Bases.end ());
    for (int i = 1; i <= b; ++ i) {
        int pos = Bases[i].position;
        if (Bases_at[pos].empty () || Bases_at[pos].back ().second < Bases[i].gold)
            Bases_at[pos].emplace_back (Bases[i].defense, Bases[i].gold);
    }

    int source = 0, sink = s + 1;
    Dinic dinic (s + 2, source, sink);
    int64_t ans = 0LL;
    for (int i = 1; i <= s; ++ i) {
        bool found = false;
        for (int p = 1; p <= n; ++ p) {
            if (Cost[Ships[i].position][p] > Ships[i].fuel)
                continue;
            auto it = std::upper_bound (Bases_at[p].begin (), Bases_at[p].end (), std::make_pair (Ships[i].strength, Inf));
            if (it != Bases_at[p].begin ())
                -- it, found = true, Value[i] = std::max (Value[i], it->second);
        }
        Value[i] -= Ships[i].price;
        if (!found)
            Value[i] = -Inf;
        if (Value[i] >= 0)
            ans += Value[i], dinic.add_edge (source, i, Value[i]);
        else
            dinic.add_edge (i, sink, -Value[i]);
    }

    for (int i = 1; i <= k; ++ i)
        std::cin >> u >> v,
        dinic.add_edge (u, v, Inf);

    std::cout << ans - dinic.max_flow ();

    return 0;
}

#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <utility>
#include <limits>

struct base_t {
    int64_t position, defense, gold;
    friend std::istream& operator >> (std::istream& flux, base_t& b) {
        flux >> b.position >> b.defense >> b.gold;
        return flux;
    }
    bool operator < (const base_t& b) const {
        return this->defense < b.defense;
    }
};

struct ship_t {
    int64_t position, strength, fuel, price;
    friend std::istream& operator >> (std::istream& flux, ship_t& s) {
        flux >> s.position >> s.strength >> s.fuel >> s.price;
        return flux;
    }
};

class Dinic;
class Flow_Edge {
private:
    int from, to;
    int64_t capacity, flow = 0LL;
public:
    Flow_Edge (const int& from, const int& to, const int64_t& capacity): from (from), to (to), capacity (capacity) {
    }
    friend Dinic;
};

constexpr auto Inf = std::numeric_limits <int64_t>::max () >> 1LL;
using Ip = std::pair <int64_t, int64_t>;
using Vi = std::vector <int>;
using VVi = std::vector <Vi>;
using Vi64 = std::vector <int64_t>;
using VVi64 = std::vector <Vi64>;
using VIp = std::vector <Ip>;
using VVIp = std::vector <VIp>;
using Vf = std::vector <Flow_Edge>;
using Vs = std::vector <ship_t>;
using Vb = std::vector <base_t>;
using Qi = std::queue <int>;

class Dinic {
private:
    Vf Edges;
    VVi Adj;
    int n, s, t;
    Vi Level, Ptr;
    Qi Q;

    bool bfs () {
        while (!Q.empty ()) {
            int v = Q.front (); Q.pop ();
            for (const auto& id: Adj[v]) {
                if (Edges[id].capacity - Edges[id].flow < 1)
                    continue;
                if (Level[Edges[id].to] != -1)
                    continue;
                Level[Edges[id].to] = Level[v] + 1;
                Q.push (Edges[id].to);
            }
        }
        return Level[t] != -1;
    }
    int64_t dfs (const int& v, const int64_t& pushed) {
        if (!pushed)
            return 0LL;
        if (v == t)
            return pushed;
        for (int& cid = Ptr[v]; cid < (int)Adj[v].size (); ++ cid) {
            int id = Adj[v][cid], u = Edges[id].to;
            if (Level[v] + 1 != Level[u] || Edges[id].capacity - Edges[id].flow < 1)
                continue;
            int64_t transport = dfs (u, std::min (pushed, Edges[id].capacity - Edges[id].flow));
            if (!transport)
                continue;
            Edges[id].flow += transport;
            Edges[id ^ 1].flow -= transport;
            return transport;
        }
        return 0LL;
    }
public:
    Dinic (const int& n, const int& s, const int& t): n (n), s (s), t (t) {
        Adj.resize (n), Level.resize (n), Ptr.resize (n);
    }
    void add_edge (const int& u, const int& v, const int64_t& cap) {
        if (u == v) return;
        Edges.emplace_back (u, v, cap);
        Adj[u].emplace_back (Edges.size () - 1);
        Edges.emplace_back (v, u, 0);
        Adj[v].emplace_back (Edges.size () - 1);
    }
    int64_t max_flow () {
        int64_t f = 0LL;
        while (true) {
            std::fill (Level.begin (), Level.end (), -1);
            Level[s] = 0;
            Q.push (s);
            if (!bfs ())
                break;
            std::fill (Ptr.begin (), Ptr.end (), 0);
            while (int64_t pushed = dfs (s, Inf))
                f += pushed;
        }
        return f;
    }
};

int n, m, u, v, s, b, k;
Vi64 Value;
VVi64 Cost;
Vs Ships;
Vb Bases;
VVIp Bases_at;

int main () {
    std::ios_base::sync_with_stdio (false), std::cin.tie (nullptr), std::cout.tie (nullptr);
    std::cin >> n >> m;
    Cost.assign (n + 1, Vi64 (n + 1, Inf));
    for (int i = 1; i <= n; ++ i) Cost[i][i] = 0LL;
    for (int i = 1; i <= m; ++ i)
        std::cin >> u >> v, Cost[u][v] = Cost[v][u] = std::min (Cost[u][v], 1LL);

    for (int k = 1; k <= n; ++ k)
        for (int i = 1; i <= n; ++ i)
            for (int j = 1; j <= n; ++ j)
                Cost[i][j] = std::min (Cost[i][j], Cost[i][k] + Cost[k][j]);

    std::cin >> s >> b >> k;
    Value.resize (s + 1), Bases_at.resize (n + 1);
    Ships.resize (s + 1), Bases.resize (b + 1);
    for (int i = 1; i <= s; ++ i)
        std::cin >> Ships[i];
    for (int i = 1; i <= b; ++ i)
        std::cin >> Bases[i];

    std::sort (Bases.begin (), Bases.end ());
    for (int i = 1; i <= b; ++ i) {
        int pos = Bases[i].position;
        if (Bases_at[pos].empty () || Bases_at[pos].back ().second < Bases[i].gold)
            Bases_at[pos].emplace_back (Bases[i].defense, Bases[i].gold);
    }

    int source = 0, sink = s + 1;
    Dinic dinic (s + 2, source, sink);
    int64_t ans = 0LL;
    for (int i = 1; i <= s; ++ i) {
        bool found = false;
        for (int p = 1; p <= n; ++ p) {
            if (Cost[Ships[i].position][p] > Ships[i].fuel)
                continue;
            auto it = std::upper_bound (Bases_at[p].begin (), Bases_at[p].end (), std::make_pair (Ships[i].strength, Inf));
            if (it != Bases_at[p].begin ())
                -- it, found = true, Value[i] = std::max (Value[i], it->second);
        }
        Value[i] -= Ships[i].price;
        if (!found)
            Value[i] = -Inf;
        if (Value[i] >= 0)
            ans += Value[i], dinic.add_edge (source, i, Value[i]);
        else
            dinic.add_edge (i, sink, -Value[i]);
    }

    for (int i = 1; i <= k; ++ i)
        std::cin >> u >> v,
        dinic.add_edge (u, v, Inf);

    std::cout << ans - dinic.max_flow ();

    return 0;
}

#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <utility>
#include <limits>

struct base_t {
    int64_t position, defense, gold;
    friend std::istream& operator >> (std::istream& flux, base_t& b) {
        flux >> b.position >> b.defense >> b.gold;
        return flux;
    }
    bool operator < (const base_t& b) const {
        //if (this->defense != b.defense)
            return this->defense < b.defense;
        //return this->gold < b.gold;
    }
};

struct ship_t {
    int64_t position, strength, fuel, price;
    friend std::istream& operator >> (std::istream& flux, ship_t& s) {
        flux >> s.position >> s.strength >> s.fuel >> s.price;
        return flux;
    }
};

struct Flow_Edge {
    int from, to;
    int64_t capacity, flow = 0LL;
    Flow_Edge (const int& from, const int& to, const int64_t& capacity): from (from), to (to), capacity (capacity) {
    }
};

constexpr int64_t Inf = 1e12 + 42;
using Ip = std::pair <int64_t, int64_t>;
using Vi = std::vector <int>;
using VVi = std::vector <Vi>;
using Vi64 = std::vector <int64_t>;
using VVi64 = std::vector <Vi64>;
using VIp = std::vector <Ip>;
using VVIp = std::vector <VIp>;
using Vf = std::vector <Flow_Edge>;
using Vs = std::vector <ship_t>;
using Vb = std::vector <base_t>;
using Qi = std::queue <int>;

struct Dinic {
    Vf Edges;
    VVi Adj;
    int n, s, t;
    Vi Level, Ptr;
    Qi Q;
    Dinic (const int& n, const int& s, const int& t): n (n), s (s), t (t) {
        Adj.resize (n), Level.resize (n), Ptr.resize (n);
    }
    void add_edge (const int& u, const int& v, const int64_t& cap) {
        if (u == v) return;
        Edges.emplace_back (Flow_Edge (u, v, cap));
        Adj[u].emplace_back (Edges.size () - 1);
        Edges.emplace_back (Flow_Edge (v, u, 0));
        Adj[v].emplace_back (Edges.size () - 1);
    }
    bool bfs () {
        while (!Q.empty ()) {
            int v = Q.front (); Q.pop ();
            for (const auto& id: Adj[v]) {
                if (Edges[id].capacity - Edges[id].flow < 1)
                    continue;
                if (Level[Edges[id].to] != -1)
                    continue;
                Level[Edges[id].to] = Level[v] + 1;
                Q.push (Edges[id].to);
            }
        }
        return Level[t] != -1;
    }
    int64_t dfs (const int& v, const int64_t& pushed) {
        if (!pushed)
            return 0LL;
        if (v == t)
            return pushed;
        for (int& cid = Ptr[v]; cid < (int)Adj[v].size (); ++ cid) {
            int id = Adj[v][cid], u = Edges[id].to;
            if (Level[v] + 1 != Level[u] || Edges[id].capacity - Edges[id].flow < 1)
                continue;
            int64_t transport = dfs (u, std::min (pushed, Edges[id].capacity - Edges[id].flow));
            if (!transport)
                continue;
            Edges[id].flow += transport;
            Edges[id ^ 1].flow -= transport;
            return transport;
        }
        return 0LL;
    }
    int64_t max_flow () {
        int64_t f = 0LL;
        while (true) {
            std::fill (Level.begin (), Level.end (), -1);
            Level[s] = 0;
            Q.push (s);
            if (!bfs ())
                break;
            std::fill (Ptr.begin (), Ptr.end (), 0);
            while (int64_t pushed = dfs (s, Inf))
                f += pushed;
        }
        return f;
    }
};

int n, m, u, v, s, b, k;
Vi64 Value;
VVi64 Cost;
Vs Ships;
Vb Bases;
VVIp Bases_at;

int main () {
    std::cin >> n >> m;
    Cost.assign (n + 1, Vi64 (n + 1, Inf));
    for (int i = 1; i <= n; ++ i) Cost[i][i] = 0LL;
    for (int i = 1; i <= m; ++ i)
        std::cin >> u >> v, Cost[u][v] = Cost[v][u] = std::min (Cost[u][v], 1LL);

    for (int k = 1; k <= n; ++ k)
        for (int i = 1; i <= n; ++ i)
            for (int j = 1; j <= n; ++ j)
                Cost[i][j] = std::min (Cost[i][j], Cost[i][k] + Cost[k][j]);

    std::cin >> s >> b >> k;
    Value.resize (s + 1), Bases_at.resize (n + 1);
    Ships.resize (s + 1), Bases.resize (b + 1);
    for (int i = 1; i <= s; ++ i)
        std::cin >> Ships[i];
    for (int i = 1; i <= b; ++ i)
        std::cin >> Bases[i];

    std::sort (Bases.begin (), Bases.end ());
    for (int i = 1; i <= b; ++ i) {
        int pos = Bases[i].position;
        if (Bases_at[pos].empty () || Bases_at[pos].back ().second < Bases[i].gold)
            Bases_at[pos].emplace_back (std::make_pair (Bases[i].defense, Bases[i].gold));
    }

    int source = 0, sink = s + 1;
    Dinic dinic (s + 2, source, sink);
    int64_t ans = 0LL;
    for (int i = 1; i <= s; ++ i) {
        bool found = false;
        for (int p = 1; p <= n; ++ p) {
            if (Cost[Ships[i].position][p] > Ships[i].fuel)
                continue;
            auto it = std::upper_bound (Bases_at[p].begin (), Bases_at[p].end (), std::make_pair (Ships[i].strength, Inf));
            if (it != Bases_at[p].begin ())
                -- it, found = true, Value[i] = std::max (Value[i], it->second);
        }
        Value[i] -= Ships[i].price;
        if (!found)
            Value[i] = -Inf;
        if (Value[i] >= 0)
            ans += Value[i], dinic.add_edge (source, i, Value[i]);
        else
            dinic.add_edge (i, sink, -Value[i]);
    }

    for (int i = 1; i <= k; ++ i)
        std::cin >> u >> v,
        dinic.add_edge (u, v, Inf);

    std::cout << ans - dinic.max_flow ();

    return 0;
}

#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <utility>
#include <limits>

struct base_t {
    int64_t position, defense, gold;
    friend std::istream& operator >> (std::istream& flux, base_t& b) {
        flux >> b.position >> b.defense >> b.gold;
        return flux;
    }
    bool operator < (const base_t& b) const {
        return this->defense < b.defense;
    }
};

struct ship_t {
    int64_t position, strength, fuel, price;
    friend std::istream& operator >> (std::istream& flux, ship_t& s) {
        flux >> s.position >> s.strength >> s.fuel >> s.price;
        return flux;
    }
};

struct Flow_Edge {
    int from, to;
    int64_t capacity, flow = 0LL;
    Flow_Edge (const int& from, const int& to, const int64_t& capacity): from (from), to (to), capacity (capacity) {
    }
};

constexpr int64_t Inf = 1e12 + 42;
using Ip = std::pair <int64_t, int64_t>;
using Vi = std::vector <int>;
using VVi = std::vector <Vi>;
using Vi64 = std::vector <int64_t>;
using VVi64 = std::vector <Vi64>;
using VIp = std::vector <Ip>;
using VVIp = std::vector <VIp>;
using Vf = std::vector <Flow_Edge>;
using Vs = std::vector <ship_t>;
using Vb = std::vector <base_t>;
using Qi = std::queue <int>;

struct Dinic {
    Vf Edges;
    VVi Adj;
    int n, s, t;
    Vi Level, Ptr;
    Qi Q;
    Dinic (const int& n, const int& s, const int& t): n (n), s (s), t (t) {
        Adj.resize (n), Level.resize (n), Ptr.resize (n);
    }
    void add_edge (const int& u, const int& v, const int64_t& cap) {
        if (u == v) return;
        Edges.emplace_back (Flow_Edge (u, v, cap));
        Adj[u].emplace_back (Edges.size () - 1);
        Edges.emplace_back (Flow_Edge (v, u, 0));
        Adj[v].emplace_back (Edges.size () - 1);
    }
    bool bfs () {
        while (!Q.empty ()) {
            int v = Q.front (); Q.pop ();
            for (const auto& id: Adj[v]) {
                if (Edges[id].capacity - Edges[id].flow < 1)
                    continue;
                if (Level[Edges[id].to] != -1)
                    continue;
                Level[Edges[id].to] = Level[v] + 1;
                Q.push (Edges[id].to);
            }
        }
        return Level[t] != -1;
    }
    int64_t dfs (const int& v, const int64_t& pushed) {
        if (!pushed)
            return 0LL;
        if (v == t)
            return pushed;
        for (int& cid = Ptr[v]; cid < (int)Adj[v].size (); ++ cid) {
            int id = Adj[v][cid], u = Edges[id].to;
            if (Level[v] + 1 != Level[u] || Edges[id].capacity - Edges[id].flow < 1)
                continue;
            int64_t transport = dfs (u, std::min (pushed, Edges[id].capacity - Edges[id].flow));
            if (!transport)
                continue;
            Edges[id].flow += transport;
            Edges[id ^ 1].flow -= transport;
            return transport;
        }
        return 0LL;
    }
    int64_t max_flow () {
        int64_t f = 0LL;
        while (true) {
            std::fill (Level.begin (), Level.end (), -1);
            Level[s] = 0;
            Q.push (s);
            if (!bfs ())
                break;
            std::fill (Ptr.begin (), Ptr.end (), 0);
            while (int64_t pushed = dfs (s, Inf))
                f += pushed;
        }
        return f;
    }
};

int n, m, u, v, s, b, k;
Vi64 Value;
VVi64 Cost;
Vs Ships;
Vb Bases;
VVIp Bases_at;

int main () {
    std::cin >> n >> m;
    Cost.assign (n + 1, Vi64 (n + 1, Inf));
    for (int i = 1; i <= n; ++ i) Cost[i][i] = 0LL;
    for (int i = 1; i <= m; ++ i)
        std::cin >> u >> v, Cost[u][v] = Cost[v][u] = std::min (Cost[u][v], 1LL);

    for (int k = 1; k <= n; ++ k)
        for (int i = 1; i <= n; ++ i)
            for (int j = 1; j <= n; ++ j)
                Cost[i][j] = std::min (Cost[i][j], Cost[i][k] + Cost[k][j]);

    std::cin >> s >> b >> k;
    Value.resize (s + 1), Bases_at.resize (n + 1);
    Ships.resize (s + 1), Bases.resize (b + 1);
    for (int i = 1; i <= s; ++ i)
        std::cin >> Ships[i];
    for (int i = 1; i <= b; ++ i)
        std::cin >> Bases[i];

    std::sort (Bases.begin (), Bases.end ());
    for (int i = 1; i <= b; ++ i) {
        int pos = Bases[i].position;
        if (Bases_at[pos].empty () || Bases_at[pos].back ().second < Bases[i].gold)
            Bases_at[pos].emplace_back (std::make_pair (Bases[i].defense, Bases[i].gold));
    }

    int source = 0, sink = s + 1;
    Dinic dinic (s + 2, source, sink);
    int64_t ans = 0LL;
    for (int i = 1; i <= s; ++ i) {
        bool found = false;
        for (int p = 1; p <= n; ++ p) {
            if (Cost[Ships[i].position][p] > Ships[i].fuel)
                continue;
            auto it = std::upper_bound (Bases_at[p].begin (), Bases_at[p].end (), std::make_pair (Ships[i].strength, Inf));
            if (it != Bases_at[p].begin ())
                -- it, found = true, Value[i] = std::max (Value[i], it->second);
        }
        Value[i] -= Ships[i].price;
        if (!found)
            Value[i] = -Inf;
        if (Value[i] >= 0)
            ans += Value[i], dinic.add_edge (source, i, Value[i]);
        else
            dinic.add_edge (i, sink, -Value[i]);
    }

    for (int i = 1; i <= k; ++ i)
        std::cin >> u >> v,
        dinic.add_edge (u, v, Inf);

    std::cout << ans - dinic.max_flow ();

    return 0;
}

#pragma GCC optimize(3)
#include<bits/stdc++.h>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/tree_policy.hpp>
#include<ext/pb_ds/priority_queue.hpp>
#define MAXN 105
#define MAXK 200005
#define MAXV 200005
#define INF 100000000000000LL
#define MOD 1000000007
#define F first
#define S second
using namespace std;
using namespace __gnu_pbds;
typedef long long ll;
typedef pair<int,int> P;
typedef tree<int,null_type,less<int>,rb_tree_tag,tree_order_statistics_node_update> ordered_set;
typedef __gnu_pbds::priority_queue<int,greater<int>,pairing_heap_tag> pq;
ll n,m;
ll d[MAXN][MAXN];
ll s,b,k;
ll sx[MAXK],sa[MAXK],sf[MAXK],sp[MAXK];
ll bx[MAXK],bd[MAXK],bg[MAXK];
void floyd_warshall()
{
    for(ll k=1;k<=n;k++)
        for(ll i=1;i<=n;i++)
          for(ll j=1;j<=n;j++)
              d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
}
struct edge{ll to,cap,rev;};
vector<edge> G[MAXV];
ll level[MAXV];
ll iter[MAXV];
vector<ll> dis[MAXN],res[MAXN];
void add_edge(ll from,ll to,ll cap)
{
    G[from].push_back((edge){to,cap,(int)G[to].size()});
    G[to].push_back((edge){from,0,(int)G[from].size()-1});
}
void bfs(ll s)
{
    memset(level,-1,sizeof(level));
    queue<int> que;
    level[s]=0;
    que.push(s);
    while(!que.empty())
    {
        ll v=que.front(); que.pop();
        for(ll i=0;i<(int)G[v].size();i++)
        {
            edge &e=G[v][i];
            if(e.cap>0&&level[e.to]<0)
            {
                level[e.to]=level[v]+1;
                que.push(e.to);
            }
        }
    }
}

ll dfs(ll v,ll t,ll f)
{
    if(v==t) return f;
    for(ll &i=iter[v];i<(int)G[v].size();i++)
    {
        edge &e=G[v][i];
        if(level[v]<level[e.to]&&e.cap>0)
        {
            ll d=dfs(e.to,t,min(f,e.cap));
            if(d>0)
            {
                e.cap-=d;
                G[e.to][e.rev].cap+=d;
                return d;
            }
        }
    }
    return 0;
}
ll max_flow(ll s,ll t)
{
    ll flow=0;
    for(;;)
    {
        bfs(s);
        if(level[t]<0) return flow;
        memset(iter,0,sizeof(iter));
        ll f;
        while((f=dfs(s,t,INF))>0)
          flow+=f;
    }
}
ll val[MAXK];
int main()
{
    scanf("%lld%lld",&n,&m);
    for(ll i=1;i<=n;i++)
        for(ll j=1;j<=n;j++)
            d[i][j]=(i==j?0:INF);
    for(ll i=0;i<m;i++)
    {
        ll u,v;
        scanf("%lld%lld",&u,&v);
        d[u][v]=d[v][u]=1;
    }
    floyd_warshall();
    scanf("%lld%lld%lld",&s,&b,&k);
    for(ll i=1;i<=s;i++) scanf("%lld%lld%lld%lld",&sx[i],&sa[i],&sf[i],&sp[i]);
    for(ll i=1;i<=b;i++) scanf("%lld%lld%lld",&bx[i],&bd[i],&bg[i]);
    for(ll i=1;i<=b;i++)
    {
        dis[bx[i]].push_back(bd[i]);
    }
    for(ll i=1;i<=n;i++)
    {
        sort(dis[i].begin(),dis[i].end());
        dis[i].erase(unique(dis[i].begin(),dis[i].end()),dis[i].end());
        res[i].resize(dis[i].size());
    }
    for(ll i=1;i<=b;i++)
    {
        ll id=lower_bound(dis[bx[i]].begin(),dis[bx[i]].end(),bd[i])-dis[bx[i]].begin();
        res[bx[i]][id]=max(res[bx[i]][id],bg[i]);
    }
    for(ll i=1;i<=n;i++)
        for(ll j=1;j<(int)res[i].size();j++)
            res[i][j]=max(res[i][j],res[i][j-1]);
    for(ll i=1;i<=s;i++) val[i]=-INF;
    for(ll i=1;i<=s;i++)
        for(ll j=1;j<=n;j++)
        {
            if(sf[i]<d[sx[i]][j]) continue;
            if(dis[j].size()==0) continue;
            ll id=upper_bound(dis[j].begin(),dis[j].end(),sa[i])-dis[j].begin()-1;
            if(id<0) continue;
            id=min(id,(ll)res[j].size()-1);
            val[i]=max(val[i],res[j][id]-sp[i]);
        }
    ll ans=0;
    for(ll i=0;i<k;i++)
    {
        ll u,v;
        scanf("%lld%lld",&u,&v);
        add_edge(u,v,INF);
    }
    ll src=s+1,dest=s+2;
    for(ll i=1;i<=s;i++)
    {
        if(val[i]>0)
        {
            add_edge(src,i,val[i]);
            ans+=val[i];
        }
        else
        {
            add_edge(i,dest,-val[i]);
        }
    }
    ans-=max_flow(src,dest);
    printf("%lld\n",ans);
    return 0;
}

#include<bits/stdc++.h>

using namespace std;

#define double long double

typedef pair<int,int> ii;
typedef pair<int,long long> il;
typedef pair<long long,long long> ll;
typedef pair<ll,int> lli;
typedef pair<long long,int> li;
typedef pair<double,double> dd;
typedef pair<ii,int> iii;
typedef pair<double,int> di;
typedef pair<int,ii> iii2;
typedef pair<ii,ii> iiii;
typedef vector<int> vi;
long long mod = 1000000007LL;
long long large = 2000000000000000000LL;

struct Edge {
	int from,to;
	long long cap,flow;
};

struct Dinic {
	int n,m,s,t;
	vector<Edge> edges;
	vector<vector<int> > G;
	vector<bool> vis;
	vector<int> dis;
	vector<int> cur;
	void init(int maxn){
		edges.clear();
		G.assign(maxn+10,vector<int>(0));
		vis.assign(maxn+10,false);
		dis.assign(maxn+10,0);
		cur.assign(maxn+10,0);
		n=maxn;
	}
	void addEdge(int from,int to,long long cap){
		edges.push_back((Edge){from,to,cap,0});
		edges.push_back((Edge){to,from,0,0});
		m=edges.size();
		G[from].push_back(m-2);
		G[to].push_back(m-1);
	}
	bool BFS() {
		vis.assign(n+10,false);
		queue<int> q;
		q.push(s);
		dis[s]=0;
		vis[s]=true;
		while(!q.empty()){
			int u=q.front();
			q.pop();
			for(int i=0;i<(int)G[u].size();i++){
				Edge& e=edges[G[u][i]];
				if(!vis[e.to]&&e.cap>e.flow){
					vis[e.to]=1;
					dis[e.to]=dis[u]+1;
					q.push(e.to);
				}
			}
		}
		return vis[t];
	}
	long long DFS(int x,long long a){
		if(x==t||a==0) return a;
		long long flow=0,f;
		for(int& i=cur[x];i<(int)G[x].size();i++){
			Edge& e=edges[G[x][i]];
			if(dis[x]+1==dis[e.to]&&(f=DFS(e.to,min(a,e.cap-e.flow)))>0){
				e.flow+=f;
				edges[G[x][i]^1].flow-=f;
				flow+=f;
				a-=f;
				if(a==0) break;
			}
		}
		return flow;
	}
	long long maxflow(int s,int t){
		this->s=s;
		this->t=t;
		long long flow=0;
		while(BFS()){
			cur.assign(n+10,0);
			flow+=DFS(s,large);
		}
		return flow;
	}
	void clearflow(){
		vis.assign(n+10,false);
		dis.assign(n+10,0);
		cur.assign(n+10,0);
		for(int i=0;i<(int)edges.size();i++){
			edges[i].flow=0;
		}
	}
};

int main(){

	int n,m;
	cin>>n>>m;
	vector<vector<int> > g(n,vector<int>(n,1000000000));
	for(int i=0;i<m;i++){
		int x,y;
		cin>>x>>y;
		x--;y--;
		g[x][y] = g[y][x] =1;
	}

	for(int i=0;i<n;i++) g[i][i] = 0;
	for(int k=0;k<n;k++) for(int i=0;i<n;i++) for(int j=0;j<n;j++) g[i][j] = min(g[i][j],g[i][k]+g[k][j]);

	int s,b;
	cin>>s>>b;

	int k;
	cin>>k;

	vector<int> ps(s,0),a(s,0),f(s,0),p(s,0);
	vector<int> pb(b,0),d(b,0),gold(b,0);
	for(int i=0;i<s;i++){
		cin>>ps[i]>>a[i]>>f[i]>>p[i];
		ps[i]--;
	}
	for(int i=0;i<b;i++){
		cin>>pb[i]>>d[i]>>gold[i];
		pb[i]--;
	}

	vector<vector<ii> > adj(n,vector<ii>());
	for(int i=0;i<b;i++){
		adj[pb[i]].push_back(ii(d[i],gold[i]));
	}
	for(int i=0;i<n;i++) sort(adj[i].begin(),adj[i].end());
	for(int i=0;i<n;i++){
		for(int j=0;j<(int)adj[i].size();j++){
			if(j) adj[i][j].second = max(adj[i][j].second,adj[i][j-1].second);
		}
	}

	for(int i=0;i<s;i++){
		int ans = -1;
		for(int j=0;j<n;j++){
			if(g[ps[i]][j]>f[i]) continue;
			int pt = upper_bound(adj[j].begin(),adj[j].end(),ii(a[i],1000000010))-adj[j].begin();
			pt--;
			if(pt>=0) ans = max(ans,adj[j][pt].second);
		}
		if(ans!=-1) p[i] = ans-p[i];
		else p[i] = -large;
	}

	Dinic din;
	din.init(s+10);
	int st = s;
	int en = st+1;
	long long sum = 0;
	for(int i=0;i<s;i++){
		if(p[i]>0){
			din.addEdge(st,i,p[i]);
			sum+=p[i];
		}else din.addEdge(i,en,-p[i]);
	}

	for(int i=0;i<k;i++){
		int x,y;
		cin>>x>>y;
		x--;y--;
		din.addEdge(x,y,large);
	}

	cout<<sum-din.maxflow(st,en)<<endl;

    return 0;
}

#include <bits/stdc++.h>
using namespace std;
#define pb push_back

typedef long long ll;

#define N 105
#define M 100005
template <class T> void chkmax(T &a, T b) {if (a < b) a = b;}
//template <class T> void chkmin(T &a, T b) {if (a > b) a = b;}

vector <int> v[N];
vector <int> vs[N];

int n, m;
int nn, mm, kk;

int f[M], d[M], g[M], a[M], x[M], y[M], p[M];
int id[M];

bool cmpa(int x, int y) {
	return a[x] < a[y];
}

int dd[N];

int fen[N];

int val[M<<1], vals;
void update(int k, int v) {
    for ( ; k <= n; k += k & -k) {
        chkmax(fen[k], v);
    }
    return;
}
const int inf = 0x3f3f3f3f;
int calc_mx(int k) {
	int res = -inf;
    for ( ; k; k -= k & -k) {
        chkmax(res, fen[k]);
    }
    return res;
}

int rd[M];
void solve(int k) {
    memset(dd, -1, sizeof dd);
    memset(fen, -1, sizeof fen);
    queue <int> Q;
    Q.push(k), dd[k] = 1;
    while (!Q.empty()) {
		int x = Q.front(); Q.pop();
		for (auto y : v[x]) if (dd[y] < 0) {
			dd[y] = dd[x] + 1;
            Q.push(y);
		}
    }
    int t = 0;
    for (int i = 1; i <= mm && t < vs[k].size(); i ++) {
        int kk = id[i];
		while (t < vs[k].size() && a[vs[k][t]] < d[kk]) {
            int u = vs[k][t];
			chkmax(rd[u], calc_mx(f[u]));
            t ++;
		}
        if (dd[y[kk]] > 0) update(dd[y[kk]], g[kk]);
    }
    while (t < vs[k].size()) {
        int u = vs[k][t];
        chkmax(rd[u], calc_mx(f[u]));
        t ++;
    }
    return;
}

vector <int> vv[M];

bool vd[M], vis[M];

void dfs(int k) {
    vd[k] = 1; vis[k] = 1;
    for (auto x : vv[k]) {
        if (vd[x]) continue;
        dfs(x);
    }
    return;
}

map <int, int> H;

int tot;

const ll linf = 1e16;

struct Dinic {
	struct edge {
		int u, v;
		ll cap, flow;
		edge() {}
		edge(int u, int v, ll cap): u(u), v(v), cap(cap), flow(0) {}
	};
	int n;
	vector <edge> E;
	vector < vector <int> > g;
	vector <int> d, pt;

	Dinic(int n): n(n), E(0), g(n), d(n), pt(n) {}
	Dinic() {}
	void init(int _n) {
		n = _n;
		g.resize(n); d.resize(n);
		E.resize(0); pt.resize(n);
		for (int i = 0; i < n; i ++) g[i].clear();
	}
	void add_edge(int u, int v, ll cap) {
		if (u != v) {
			E.push_back(edge(u, v, cap));
			g[u].push_back(E.size() - 1);
			E.push_back(edge(v, u, 0));
			g[v].push_back(E.size() - 1);
		}
	}

	bool BFS(int S, int T) {
		queue<int> q;
		q.push(S);
		fill(d.begin(), d.end(), n + 1);
		d[S] = 0;
		while(!q.empty()) {
			int u = q.front(); q.pop();
			if (u == T) break;
			for (int i = 0; i < g[u].size(); i ++) {
				int k = g[u][i];
				edge &e = E[k];
				if (e.flow < e.cap && d[e.v] > d[e.u] + 1) {
					d[e.v] = d[e.u] + 1;
					q.push(e.v);
				}
			}
		}
		return d[T] != n + 1;
	}

	ll DFS(int u, int T, ll flow = -1) {
		if (u == T || flow == 0) return flow;
		for (int &i = pt[u]; i < g[u].size(); ++i) {
			edge &e = E[g[u][i]];
			edge &oe = E[g[u][i]^1];
			if (d[e.v] == d[e.u] + 1) {
				ll amt = e.cap - e.flow;
				if (flow != -1 && amt > flow) amt = flow;
				if (ll pushed = DFS(e.v, T, amt)) {
					e.flow += pushed;
					oe.flow -= pushed;
					return pushed;
				}
			}
		}
		return 0;
	}

	ll maxflow(int S, int T) {
		ll res = 0;
		while (BFS(S, T)) {
			fill(pt.begin(), pt.end(), 0);
			while (ll flow = DFS(S, T)) res += flow;
		}
		return res;
	}
} A;

ll tot_sum;

bool vvis[M];

void add_edge(int x, int y) {
	vvis[x] = vvis[y] = 1;
    if (!H.count(x)) {
        H[x] = ++ tot;
        int t = rd[x] - p[x];
        if (t < 0) A.add_edge(tot, 1, -t);
        else A.add_edge(0, tot, t), tot_sum += t;
    }
    if (!H.count(y)) {
        H[y] = ++ tot;
        int t = rd[y] - p[y];
        if (t < 0) A.add_edge(tot, 1, -t);
        else A.add_edge(0, tot, t), tot_sum += t;
    }
    A.add_edge(H[x], H[y], linf);
}

inline char nc() {
    static char buf[100000],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
template <class T> void read(T &x){
	char c=nc(),b=1;
	for (;!((c>='0'&&c<='9')||c==EOF);c=nc()) if (c=='-') b=-b;
	for (x=0;c>='0'&&c<='9';x=x*10+c-'0',c=nc()); x*=b;
}

bool cmpd(int x, int y) {
	return d[x] < d[y];
}

int main() {
    memset(rd, -1, sizeof rd);
	read(n), read(m);
    for (int i = 1; i <= m; i ++) {
		int x, y;
		read(x), read(y);
		v[x].pb(y);
		v[y].pb(x);
    }
    read(nn), read(mm), read(kk);
    for (int i = 1; i <= nn; i ++) {
		read(x[i]), read(a[i]), read(f[i]), read(p[i]);
        if (f[i] >= n) f[i] = n-1;
        f[i] ++;
        val[vals++] = a[i];
        vs[x[i]].pb(i);
    }
    for (int i = 1; i <= mm; i ++) {
    	read(y[i]), read(d[i]), read(g[i]);
        val[vals++] = d[i];
        id[i] = i;
    }
    sort(val, val+vals);
    vals = unique(val, val+vals) - val;
    for (int i = 1; i <= nn; i ++) {
        a[i] = lower_bound(val, val+vals, a[i]) - val + 1;
    }
    for (int i = 1; i <= mm; i ++) {
        d[i] = lower_bound(val, val+vals, d[i]) - val + 1;
    }
    sort(id+1, id+mm+1, cmpd);
    for (int i = 1; i <= n; i ++) sort(vs[i].begin(), vs[i].end(), cmpa);
    for (int i = 1; i <= n; i ++) if (!vs[i].empty()) solve(i);
    for (int i = 1; i <= nn; i ++) if (rd[i] < 0) vis[i] = 1;
    while (kk --) {
        int x, y;
		read(x), read(y);
        vv[y].pb(x);
    }
    for (int i = 1; i <= nn; i ++) if (vis[i] && !vd[i]) dfs(i);
    A.init(3000);
    tot = 1;
    for (int i = 1; i <= nn; i ++) if (!vis[i]) {
        for (auto x : vv[i]) if (!vis[x]) {
            add_edge(x, i);
        }
    }
    ll flow = A.maxflow(0, 1);
    flow = tot_sum - flow;
    for (int i = 1; i <= nn; i ++) if (!vvis[i] && !vis[i] && rd[i] - p[i] > 0) flow += rd[i] - p[i];
    printf("%I64d\n", flow);
    return 0;
}

#pragma GCC optimize("O3")
#include <bits/stdc++.h>

using namespace std;

#define sim template<class c
#define ris return *this
#define dor > debug & operator<<
#define eni(x) sim>typename \
  enable_if<sizeof dud<c>(0) x 1, debug&>::type operator<<(c i) {
sim> struct rge { c b, e; };
sim> rge<c> range(c i, c j) { return rge<c>{i, j}; }
sim> auto dud(c*x) -> decltype(cerr<<*x, 0);
sim> char dud(...);
struct debug {
#ifdef LOCAL
~debug() { cerr << endl; }
eni(!=) cerr << boolalpha << i; ris; }
eni(==) ris << range(begin(i), end(i)); }
sim, class b dor (pair<b,c> d) {
  ris<<"("<<d.first<<", "<<d.second<<")";
}
sim dor(rge<c> d) {
  *this<<"[";
  for (auto it = d.b; it != d.e; ++it)
    *this << ", " + 2 * (it == d.b) << *it;
  ris <<" ]";
}
#else
sim dor(const c&) { ris; }
#endif
};
#define imie(...) " [" << #__VA_ARGS__ ": " << (__VA_ARGS__) << "] "

using ll = long long;
#define int ll
#define PB push_back
#define MP make_pair
#define PII pair<int, int>
#define SZ(x) ((int)(x).size())
#define FOR(i,a,b) for (int i = (a); i <= (b); ++i)
#define REP(i,n) FOR(i,0,(int)(n)-1)
#define VI vector<int>
using pii = pair<int, int>;
using pll = pair<ll, ll>;
using vi = vector<int>;
using vll = vector<ll>;

struct Dinic {
  struct Edge { int v, c, inv; };
public:
  Dinic() : n(-1) {}
  void AddEdge(int a, int b, int cap, int bi_dir) {
    if (n < max(a, b)) {
      n = max(n, max(a, b));
      ResizeVectors();
    }
    e_orig[a].PB(Edge{b, cap, SZ(e_orig[b])});
    e_orig[b].PB(Edge{a, bi_dir * cap, SZ(e_orig[a]) - 1});
  }
  int MaxFlow(int s, int t) {
    if (t > n || s > n) {
      n = max(s, t);
      ResizeVectors();
    }
    e = e_orig; int result = 0;
    while (Bfs(s, t)) {
      fill_n(beg.begin(), n + 1, 0);
      result += Dfs(s, t, kInf);
    }
    return result;
  }
  vector<bool> MinCut(int s, int t) {
    assert(!Bfs(s, t));
    vector<bool> res(n + 1);
    FOR (i, 0, n) { res[i] = (dis[i] <= n); }
    return res;
  }

  vector<PII> EdgeCut(int s, int t) {
    vector<bool> left_part = MinCut(s, t);
    vector<PII> cut;
    FOR (v, 0, n) {
      for (auto edge : e_orig[v]) {
        if (edge.c != 0 && left_part[v] && !left_part[edge.v]) {
          cut.PB({v, edge.v});
        }
      }
    }
    return cut;
  }
private:
  int n;
  vector<vector<Edge>> e_orig, e;
  VI dis, beg;

  bool Bfs(int s, int t) {
    fill_n(dis.begin(), n + 1, n + 1);
    dis[s] = 0;
    VI que;
    que.push_back(s);
    REP (i, SZ(que)) {
      int v = que[i];
      for (auto edge : e[v]) {
        int nei = edge.v;
        if (edge.c && dis[nei] > dis[v] + 1) {
          dis[nei] = dis[v] + 1;
          que.push_back(nei);
          if (nei == t) { return true; }
        }
      }
    }
    return false;
  }
  int Dfs(int v, int t, int min_cap) {
    int result = 0;
    if (v == t || min_cap == 0) { return min_cap; }
    for (int& i = beg[v]; i < SZ(e[v]); i++) {
      int nei = e[v][i].v, c = e[v][i].c;
      if (dis[nei] == dis[v] + 1 && c > 0) {
        int flow_here = Dfs(nei, t, min(min_cap, c));
        result += flow_here;
        min_cap -= flow_here;
        e[v][i].c -= flow_here;
        e[nei][e[v][i].inv].c += flow_here;
      }
      if (min_cap == 0) { break; }
    }
    return result;
  }

  void ResizeVectors() {
    e_orig.resize(n + 2);
    beg.resize(n + 2);
    dis.resize(n + 2);
  }

  #ifndef int
  #warning
  #endif
  static const int kInf = 1e18; // UWAZAC, JESLI NIE INT = LONG LONG
};

const int MaxN = 2048;
const int MaxItems = 5e5;

int n, m;
vi adj[MaxN];
int s, b, k, h;
int dist[MaxN][MaxN];
vector<pii> at_vert[MaxN];

int sp_loc[MaxItems], sp_atk[MaxItems], sp_fuel[MaxItems], sp_price[MaxItems];
int bs_loc[MaxItems], bs_def[MaxItems], bs_gold[MaxItems];

vi dep_adj[MaxItems];
bool any_dep[MaxItems];
int dep_idx[MaxItems];

int32_t main() {
  scanf("%lld%lld", &n, &m);
  for (int i = 0; i <= n; ++i) {
    for (int j = 0; j <= n; ++j) {
      dist[i][j] = 2e9;
    }
    dist[i][i] = 0;
  }

  for (int i = 0; i < m; ++i) {
    int u, v;
    scanf("%lld%lld", &u, &v);
    adj[u].push_back(v);
    adj[v].push_back(u);
    if (u != v) {
      dist[u][v] = dist[v][u] = 1;
    }
  }

  for (int k = 1; k <= n; ++k) {
    for (int i = 1; i <= n; ++i) {
      for (int j = 1; j <= n; ++j) {
        dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
      }
    }
  }

  scanf("%lld%lld%lld", &s, &b, &k);

  for (int i = 0; i < s; ++i) {
    scanf("%lld%lld%lld%lld", &sp_loc[i], &sp_atk[i], &sp_fuel[i], &sp_price[i]);
  }
  for (int i = 0; i < b; ++i) {
    scanf("%lld%lld%lld", &bs_loc[i], &bs_def[i], &bs_gold[i]);
    at_vert[bs_loc[i]].emplace_back(bs_def[i], bs_gold[i]);
  }

  for (int v = 1; v <= n; ++v) {
    auto &X = at_vert[v];
    sort(X.begin(), X.end());

    const int sz = X.size();
    int cur_max = -1;
    int ptr = 0;
    for (int i = 0; i < sz; ++i) {
      if (X[i].second <= cur_max) { continue; }
      X[ptr++] = X[i];
      cur_max = X[i].second;
    }
    X.resize(ptr);

    debug() << imie(v) << imie(X);
  }

  const int kSmallInf = 2e16;
  const ll kLargeInf = 2e16;

  vll sp_best(s, -kLargeInf);
  for (int i = 0; i < s; ++i) {
    for (int v = 1; v <= n; ++v) {
      if (sp_fuel[i] < dist[sp_loc[i]][v]) { continue; }
      const int atk = sp_atk[i];
      auto iter =
        lower_bound(at_vert[v].begin(), at_vert[v].end(),
                    pii(atk, kSmallInf));
      if (iter == at_vert[v].begin()) {
        continue;
      } else {
        int bnd = prev(iter)->second;
        sp_best[i] = max(sp_best[i], (ll)bnd - sp_price[i]);
      }
    }
    debug() << imie(i) << imie(sp_best[i]);
  }

  for (int i = 0; i < k; ++i) {
    int u, v;
    scanf("%lld%lld", &u, &v);
    --u; --v;
    any_dep[u] = any_dep[v] = true;
    dep_adj[u].PB(v);
  }

  ll ans = 0;
  int curidx = 0;
  for (int i = 0; i < s; ++i) {
    if (!any_dep[i] && sp_best[i] >= 0) {
      ans += sp_best[i];
    }
    /*if (any_dep[i]) {
      dep_idx[i] = curidx++;
    }*/
    dep_idx[i] = curidx++;
  }

  Dinic dinic;
  const int source = curidx;
  const int sink = source + 1;

  debug() << imie(source) << imie(sink);

  for (int i = 0; i < s; ++i) {
    if (!any_dep[i]) { continue; }
    if (sp_best[i] >= 0) {
      dinic.AddEdge(source, dep_idx[i], sp_best[i], 0);
      ans += sp_best[i];
    } else {
      dinic.AddEdge(dep_idx[i], sink, -sp_best[i], 0);
    }

    for (int j : dep_adj[i]) {
      dinic.AddEdge(dep_idx[i], dep_idx[j], kLargeInf, 0);
    }
  }

  const ll flow = dinic.MaxFlow(source, sink);
  ans -= flow;
  assert(ans >= 0);

  printf("%lld\n", ans);
}

#include <bits/stdc++.h>
using namespace std;

// Template Headers {{{
using pii = pair<int, int>; using vpii = vector<pii>;
using vi = vector<int>; using vvi = vector<vi>;
using ll = long long; using vll = vector<long long>;
template <class T> using min_queue = priority_queue<T, vector<T>, greater<T>>;
template <class T> istream &operator>>(istream &, vector<T> &);
template <class T> ostream &operator<<(ostream &, const vector<T> &);
template <class T, class U> istream &operator>>(istream &, pair<T, U> &);
template <class T, class U> ostream &operator<<(ostream &, const pair<T, U> &);
template<class T> struct Inf { static constexpr T inf() { return std::numeric_limits<T>::has_infinity() ? std::numeric_limits<T>::infinty() : std::numeric_limits<T>::max(); } };
template<> struct Inf<int> { static constexpr int inf() { return 0x3f3f3f3f; } };
template<> struct Inf<long long> { static constexpr long long inf() { return 0x3f3f3f3f3f3f3f3fLL; } };
constexpr int INF = Inf<int>::inf(); constexpr ll BINF = Inf<ll>::inf();
// mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
// }}}
// Dinic Maximum Flow {{{
template <class T>
class Dinic {

private:

	struct edge {
		int from, to; T cap;
		edge *rev;
		edge(int u, int v, T c) : from(u), to(v), cap(c), rev(nullptr) {}
	};

	static constexpr T INF = Inf<T>::inf();
	static constexpr int DINF = Inf<int>::inf();

	int n, s, t;
	std::vector<std::vector<edge*>> g;

public:

	Dinic(int n, int s, int t) : n(n), s(s), t(t), g(n) {}
	~Dinic() { for (auto v : g) for (edge *e : v) delete e; }

	void addEdge(int u, int v, T c) {
		edge *in = new edge(u, v, c);
		edge *out = new edge(v, u, 0);
		g[u].push_back(in); g[v].push_back(out);
		in->rev = out; out->rev = in;
	}

	T maxFlow() {
		T mxf = 0;
		std::vector<int> dist(n, DINF), vis(n);
		std::function<T(int, T)> dfs = [&] (int u, T fo) -> T {
			if (u == t) return fo;
			for (;vis[u]<int(g[u].size());vis[u]++) {
				edge *e = g[u][vis[u]];
				int v = e->to;
				if (dist[v] != dist[u] + 1 || e->cap <= 0) continue;
				T foo = dfs(v, std::min(fo, e->cap));
				if (foo > 0) {
					e->cap -= foo;
					e->rev->cap += foo;
					return foo;
				}
			}
			return 0;
		};
		for (;;) {
			for (int i=0;i<n;i++) dist[i] = DINF, vis[i] = 0;
			std::queue<int> q; q.push(s); dist[s] = 0;
			while (!q.empty()) {
				int u = q.front(); q.pop();
				if (u == t) break;
				for (edge *e: g[u]) {
					int v = e->to;
					if (e->cap > 0 && dist[v] == DINF) {
						dist[v] = dist[u] + 1;
						q.push(v);
					}
				}
			}
			if (dist[t] == DINF) break;
			while (T fo = dfs(s, INF))
				mxf += fo;
		}
		return mxf;
	}

};
template <class T> constexpr T Dinic<T>::INF;
template <class T> constexpr int Dinic<T>::DINF;
// }}}

int solve() {
	int n, m; cin >> n >> m;
	vvi dp(n, vi(n, INF));
	for (int i=0;i<m;i++) {
		int u, v; cin >> u >> v; u--, v--;
		dp[u][v] = dp[v][u] = 1;
	}
	for (int i=0;i<n;i++) dp[i][i] = 0;
	for (int k=0;k<n;k++) for (int i=0;i<n;i++) for (int j=0;j<n;j++)
		dp[i][j] = min(dp[i][j], dp[i][k] + dp[k][j]);

	int s, b, k; cin >> s >> b >> k;
	vi xs(s), as(s), fs(s), ps(s), xb(b), db(b), gb(b);
	for (int i=0;i<s;i++) {
		cin >> xs[i] >> as[i] >> fs[i] >> ps[i];
		xs[i]--;
	}
	for (int i=0;i<b;i++) {
		cin >> xb[i] >> db[i] >> gb[i];
		xb[i]--;
	}

	vll canGet(s, -BINF);

	vector<vpii> bsList(n);
	for (int i=0;i<b;i++) bsList[xb[i]].emplace_back(db[i], gb[i]);
	for (int i=0;i<n;i++) {
		sort(bsList[i].begin(), bsList[i].end());
		int z = bsList[i].size();
		for (int j=1;j<z;j++) bsList[i][j].second = max(bsList[i][j].second, bsList[i][j - 1].second);
	}
	for (int i=0;i<s;i++) for (int j=0;j<n;j++) {
		if (dp[xs[i]][j] > fs[i]) continue;
		auto it = upper_bound(bsList[j].begin(), bsList[j].end(), pii{as[i], INF});
		if (it == bsList[j].begin()) continue;
		it--;
		canGet[i] = max(canGet[i], ll(it->second));
	}
	for (int i=0;i<s;i++) canGet[i] -= ps[i];

	ll ans = 0;
	Dinic<ll> g(s + 2, s, s + 1);
	for (int i=0;i<s;i++) {
		if (canGet[i] >= 0) {
			ans += canGet[i];
			g.addEdge(s, i, canGet[i]);
		} else {
			g.addEdge(i, s + 1, -canGet[i]);
		}
	}
	for (int i=0;i<k;i++) {
		int u, v; cin >> u >> v; u--, v--;
		g.addEdge(u, v, BINF);
	}
	ans -= g.maxFlow();
	cout << ans << endl;

	return 0;
}

// Template Main {{{
int main() {
	ios::sync_with_stdio(0);
	// precompute();
	// int t; cin >> t; for (int i=1;i<=t;i++)
	solve();
	// cout << "Case #" << i << ": ", solve();
	return 0;
}

template <class T> istream &operator>>(istream &is, vector<T> &v) {
	for (auto it=v.begin();it!=v.end();++it) is >> *it;
	return is;
}

template <class T> ostream &operator<<(ostream &os, const vector<T> &v) {
	for (auto it=v.begin();it!=v.end();) os << *it, os << " \n"[++it==v.end()];
	return os;
}

template <class T, class U> istream &operator>>(istream &is, pair<T, U> &p) {
	return is >> p.first >> p.second;
}

template <class T, class U> ostream &operator<<(ostream &os, const pair<T, U> &p) {
	return os << p.first << ' ' << p.second;
}
// }}}

// vim: fdm=marker

#include <bits/stdc++.h>
using namespace std;

// Template Headers {{{
using pii = pair<int, int>; using vpii = vector<pii>;
using vi = vector<int>; using vvi = vector<vi>;
using ll = long long; using vll = vector<long long>;
template <class T> using min_queue = priority_queue<T, vector<T>, greater<T>>;
template <class T> istream &operator>>(istream &, vector<T> &);
template <class T> ostream &operator<<(ostream &, const vector<T> &);
template <class T, class U> istream &operator>>(istream &, pair<T, U> &);
template <class T, class U> ostream &operator<<(ostream &, const pair<T, U> &);
template<class T> struct Inf { static constexpr T inf() { return std::numeric_limits<T>::has_infinity() ? std::numeric_limits<T>::infinty() : std::numeric_limits<T>::max(); } };
template<> struct Inf<int> { static constexpr int inf() { return 0x3f3f3f3f; } };
template<> struct Inf<long long> { static constexpr long long inf() { return 0x3f3f3f3f3f3f3f3fLL; } };
constexpr int INF = Inf<int>::inf(); constexpr ll BINF = Inf<ll>::inf();
// mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
// }}}
// Dinic Maximum Flow {{{
template<class T>
class Dinic {

private:

	struct edge {
		int from, to; T cap;
		edge *rev;
		edge(int u, int v, T c) : from(u), to(v), cap(c), rev(nullptr) {}
	};

	static constexpr T INF = Inf<T>::inf();

	int n, s, t;
	std::vector<std::vector<edge*>> g;

public:

	Dinic(int n, int s, int t) : n(n), s(s), t(t), g(n) {}
	~Dinic() { for (auto v : g) for (edge *e : v) delete e; }

	void addEdge(int u, int v, T c) {
		edge *in = new edge(u, v, c);
		edge *out = new edge(v, u, 0);
		g[u].push_back(in); g[v].push_back(out);
		in->rev = out; out->rev = in;
	}

	T maxFlow() {
		T mxf = 0;
		std::vector<T> dist(n, INF), vis(n);
		std::function<T(int, T)> dfs = [&] (int u, T fo) -> T {
			if (u == t) return fo;
			for (;vis[u]<int(g[u].size());vis[u]++) {
				edge *e = g[u][vis[u]];
				int v = e->to;
				if (dist[v] != dist[u] + 1 || e->cap <= 0) continue;
				T foo = dfs(v, std::min(fo, e->cap));
				if (foo > 0) {
					e->cap -= foo;
					e->rev->cap += foo;
					return foo;
				}
			}
			return 0;
		};
		for (;;) {
			for (int i=0;i<n;i++) dist[i] = INF, vis[i] = 0;
			std::queue<int> q; q.push(s); dist[s] = 0;
			while (!q.empty()) {
				int u = q.front(); q.pop();
				if (u == t) break;
				for (edge *e: g[u]) {
					int v = e->to;
					if (e->cap > 0 && dist[v] == INF) {
						dist[v] = dist[u] + 1;
						q.push(v);
					}
				}
			}
			if (dist[t] == INF) break;
			while (T fo = dfs(s, INF))
				mxf += fo;
		}
		return mxf;
	}

};
template<class T> constexpr T Dinic<T>::INF;
// }}}

int solve() {
	int n, m; cin >> n >> m;
	vvi dp(n, vi(n, INF));
	for (int i=0;i<m;i++) {
		int u, v; cin >> u >> v; u--, v--;
		dp[u][v] = dp[v][u] = 1;
	}
	for (int i=0;i<n;i++) dp[i][i] = 0;
	for (int k=0;k<n;k++) for (int i=0;i<n;i++) for (int j=0;j<n;j++)
		dp[i][j] = min(dp[i][j], dp[i][k] + dp[k][j]);

	int s, b, k; cin >> s >> b >> k;
	vi xs(s), as(s), fs(s), ps(s), xb(b), db(b), gb(b);
	for (int i=0;i<s;i++) {
		cin >> xs[i] >> as[i] >> fs[i] >> ps[i];
		xs[i]--;
	}
	for (int i=0;i<b;i++) {
		cin >> xb[i] >> db[i] >> gb[i];
		xb[i]--;
	}

	vll canGet(s, -BINF);

	vector<vpii> bsList(n);
	for (int i=0;i<b;i++) bsList[xb[i]].emplace_back(db[i], gb[i]);
	for (int i=0;i<n;i++) {
		sort(bsList[i].begin(), bsList[i].end());
		int z = bsList[i].size();
		for (int j=1;j<z;j++) bsList[i][j].second = max(bsList[i][j].second, bsList[i][j - 1].second);
	}
	for (int i=0;i<s;i++) for (int j=0;j<n;j++) {
		if (dp[xs[i]][j] > fs[i]) continue;
		auto it = upper_bound(bsList[j].begin(), bsList[j].end(), pii{as[i], INF});
		if (it == bsList[j].begin()) continue;
		it--;
		canGet[i] = max(canGet[i], ll(it->second));
	}
	for (int i=0;i<s;i++) canGet[i] -= ps[i];

	ll ans = 0;
	Dinic<ll> g(s + 2, s, s + 1);
	for (int i=0;i<s;i++) {
		if (canGet[i] >= 0) {
			ans += canGet[i];
			g.addEdge(s, i, canGet[i]);
		} else {
			g.addEdge(i, s + 1, -canGet[i]);
		}
	}
	for (int i=0;i<k;i++) {
		int u, v; cin >> u >> v; u--, v--;
		g.addEdge(u, v, BINF);
	}
	ans -= g.maxFlow();
	cout << ans << endl;

	return 0;
}

// Template Main {{{
int main() {
	ios::sync_with_stdio(0);
	// precompute();
	// int t; cin >> t; for (int i=1;i<=t;i++)
	solve();
	// cout << "Case #" << i << ": ", solve();
	return 0;
}

template <class T> istream &operator>>(istream &is, vector<T> &v) {
	for (auto it=v.begin();it!=v.end();++it) is >> *it;
	return is;
}

template <class T> ostream &operator<<(ostream &os, const vector<T> &v) {
	for (auto it=v.begin();it!=v.end();) os << *it, os << " \n"[++it==v.end()];
	return os;
}

template <class T, class U> istream &operator>>(istream &is, pair<T, U> &p) {
	return is >> p.first >> p.second;
}

template <class T, class U> ostream &operator<<(ostream &os, const pair<T, U> &p) {
	return os << p.first << ' ' << p.second;
}
// }}}

// vim: fdm=marker

#include <bits/stdc++.h>
#pragma GCC optimize("Ofast,no-stack-protector")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,sse4.1,sse4.2,popcnt,abm,mmx,avx,avx2,tune=native")
using namespace std;

typedef long long i64;

struct Dinic {
	struct Edge {
		i64 flow;
		int to, next;
	};
	vector<Edge> edges;
	vector<int> adia, at, dist;
	int S, D;
	void add_Edge(int from, int to, i64 cap) {
		edges.push_back({ cap, to, adia[from] });
		adia[from] = edges.size() - 1;
		edges.push_back({ 0, from, adia[to] });
		adia[to] = edges.size() - 1;
	}
	bool bfs() {
		queue<int> q;
		fill(dist.begin(), dist.end(), 1e9);
		dist[S] = 0;
		q.push(S);
		while (!q.empty()) {
			int x = q.front();
			q.pop();
			for (int i = adia[x]; i != -1; i = edges[i].next) {
				if (dist[edges[i].to] > dist[x] + 1 && edges[i].flow) {
					dist[edges[i].to] = 1 + dist[x];
					q.push(edges[i].to);
				}
			}
		}
		return dist[D] < 1e9;
	}
	i64 dfs(int nod, i64 fmax) {
		if (nod == D)
			return fmax;
		while (at[nod] != -1) {
			Edge& e = edges[at[nod]];
			i64 f;
			if (dist[e.to] == dist[nod] + 1 && e.flow
				&& (f = dfs(e.to, min(fmax, e.flow)))) {
				e.flow -= f;
				edges[at[nod] ^ 1].flow += f;
				return f;
			}
			at[nod] = edges[at[nod]].next;
		}
		return 0;
	}
	i64 GetFlow() {
		i64 f = 0;
		while (bfs()) {
			at = adia;
			while (i64 x = dfs(S, 1e18))
				f += x;
		}
		return f;
	}
	Dinic(int n = 0, int s = 0, int d = 0) {
		S = s, D = d;
		at = dist = adia = vector<int>(n + 1, -1);
	}
};

const int NMAX = 110;
int dmin[NMAX][NMAX];
struct Object { int cost, nod, power, id, fuel, atac; };
vector <Object> ships, bases;
vector <pair <int, int>> dependencies;
int n;
int best_cost[NMAX]; /// cel mai bun cost momentan pt o baza din nod

void get_cost_nave()
{
	fill(best_cost, best_cost + n + 1, -1);

	vector <int> nv(ships.size());
	iota(nv.begin(), nv.end(), 0);

	sort(nv.begin(), nv.end(), [](int a, int b) {
		return ships[a].power < ships[b].power;
		});
	sort(bases.begin(), bases.end(), [](Object a, Object b) {
		return a.power < b.power;
		});

	int it = 0;
	for (auto i : nv) {
		while (it != bases.size() && ships[i].power >= bases[it].power) {
			best_cost[bases[it].nod] = max(best_cost[bases[it].nod], bases[it].cost);
			it++;
		}
		int best = -1;
		for (int nod = 1; nod <= n; nod++)
			if (dmin[nod][ships[i].nod] <= ships[i].fuel)
				best = max(best, best_cost[nod]);
		ships[i].atac = best;
	}
}

void read()
{
	int m, a, b;
	scanf("%d%d", &n, &m);
	fill(dmin[0], dmin[n + 1], 1e9);
	for (int i = 1; i <= n; i++)
		dmin[i][i] = 0;

	while (m--) {
		scanf("%d%d", &a, &b);
		dmin[a][b] = dmin[b][a] = 1;
	}

	for (int k = 1; k <= n; k++)
		for (int i = 1; i <= n; i++)
			for (int j = 1; j <= n; j++)
				dmin[i][j] = min(dmin[i][j], dmin[i][k] + dmin[k][j]);

	int s, k;
	scanf("%d%d%d", &s, &b, &k);
	ships.resize(s);
	bases.resize(b);
	dependencies.resize(k);

	for (auto& i : ships) {
		scanf("%d%d%d%d", &i.nod, &i.power, &i.fuel, &i.cost);
		i.fuel = min(i.fuel, 1000000);
	}
	for (auto& i : bases)
		scanf("%d%d%d", &i.nod, &i.power, &i.cost);
	for (auto& i : dependencies)
		scanf("%d%d", &i.first, &i.second);
}

int main()
{
	read();
	get_cost_nave();

	i64 ans = 0;
	int cnt = 2, S = 1, D = 2;
	const i64 inf = 1e18;

	for (auto& i : dependencies)
		i.first--, i.second--;

	for (int i = 0; i < ships.size(); i++)
		ships[i].id = ++cnt;

	Dinic flow(cnt + 1, S, D);

	for (auto i : ships) {
		if (i.atac == -1)
			flow.add_Edge(i.id, D, inf);
		else {
			int castig = i.atac - i.cost;
			if (castig > 0) {
				ans += castig;
				flow.add_Edge(S, i.id, castig);
			}
			else
				flow.add_Edge(i.id, D, -castig);
		}
	}

	for (auto i : dependencies)
		flow.add_Edge(ships[i.first].id, ships[i.second].id, inf);

	ans -= flow.GetFlow();

	cout << ans << '\n';

	return 0;
}

#include <bits/stdc++.h>

using namespace std;

#define fore(i, s, e) for(int i = s; i < e; i++)
#define SZ(a) ((int)a.size())
#define fst first
#define snd second
#define ALL(a) a.begin(),a.end()
#define pb push_back
#define FIN ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define endl '\n'
#define mset(a, b) memset(a, b, sizeof(a))
#define dbg(...) cout << "[" << #__VA_ARGS__ << "]: "; cout << to_string(__VA_ARGS__) << endl
template <typename T, size_t N> int SIZE(const T (&t)[N]){ return N; } template<typename T> int SIZE(const T &t){ return t.size(); } string to_string(const string s, int x1=0, int x2=1e9){ return '"' + ((x1 < s.size()) ? s.substr(x1, x2-x1+1) : "") + '"'; } string to_string(const char* s) { return to_string((string) s); } string to_string(const bool b) { return (b ? "true" : "false"); } string to_string(const char c){ return string({c}); } template<size_t N> string to_string(const bitset<N> &b, int x1=0, int x2=1e9){ string t = ""; for(int __iii__ = min(x1,SIZE(b)),  __jjj__ = min(x2, SIZE(b)-1); __iii__ <= __jjj__; ++__iii__){ t += b[__iii__] + '0'; } return '"' + t + '"'; } template <typename A, typename... C> string to_string(const A (&v), int x1=0, int x2=1e9, C... coords); int l_v_l_v_l = 0, t_a_b_s = 0; template <typename A, typename B> string to_string(const pair<A, B> &p) { l_v_l_v_l++; string res = "(" + to_string(p.first) + ", " + to_string(p.second) + ")"; l_v_l_v_l--; return res; } template <typename A, typename... C> string to_string(const A (&v), int x1, int x2, C... coords) { int rnk = rank<A>::value; string tab(t_a_b_s, ' '); string res = ""; bool first = true; if(l_v_l_v_l == 0) res += '\n'; res += tab + "["; x1 = min(x1, SIZE(v)), x2 = min(x2, SIZE(v)); auto l = begin(v); advance(l, x1); auto r = l; advance(r, (x2-x1) + (x2 < SIZE(v))); for (auto e = l; e != r; e = next(e)) { if (!first) { res += ", "; } first = false; l_v_l_v_l++; if(e != l){ if(rnk > 1) { res += '\n'; t_a_b_s = l_v_l_v_l; }; } else{ t_a_b_s = 0; } res += to_string(*e, coords...); l_v_l_v_l--; } res += "]"; if(l_v_l_v_l == 0) res += '\n'; return res; } void dbgm(){;} template<typename Heads, typename... Tails> void dbgm(Heads H, Tails... T){ cout << to_string(H) << " | "; dbgm(T...); }
#define dbgm(...) cout << "[" << #__VA_ARGS__ << "]: "; dbgm(__VA_ARGS__); cout << endl

typedef long long ll;

const int N = 105;
const int B = 100005;
int d[N][N], gain[B];

void floyd(int n) {
  fore(i, 0, n) d[i][i] = 0;
  fore(k, 0, n) fore(i, 0, n) fore(j, 0, n) d[i][j] = min(d[i][j], d[i][k] + d[j][k]);
}

struct ship{int x, a, f, p;};
struct base {
  int x, d, g;
};

struct node {
  vector<base> bases;
  vector<int> maxs;
  void add(base base) {
    bases.pb(base);
  }
  void prepare() {
    sort(ALL(bases), [](base a, base b)->bool{
      return a.d < b.d;
    });
    maxs.pb(-1);
    fore(i, 0, SZ(bases)) {
      maxs.pb(max(maxs.back(), bases[i].g));
    }
  }
  int bin(int s) {
    int izq = 0, der = SZ(bases) - 1;
    int res = SZ(bases);
    while(izq <= der) {
      int med = (izq + der) / 2;
      if(bases[med].d > s) res = med, der = med - 1;
      else izq = med + 1;
    }
    if(res < SZ(bases)) assert(bases[res].d > s);
    return res;
  }
  int query(int strength) {
    int p = bin(strength);
    return maxs[p];
  }
};
const ll INF = 1e15;
struct Dinic{
	int nodes,src,dst;
	vector<int> dist,q,work;
	struct edge {int to,rev;ll f,cap;};
	vector<vector<edge>> g;
	Dinic(int x):nodes(x),g(x),dist(x),q(x),work(x){}
	void add_edge(int s, int t, ll cap){
		g[s].pb((edge){t,SZ(g[t]),0,cap});
		g[t].pb((edge){s,SZ(g[s])-1,0,0});
	}
	bool dinic_bfs(){
		fill(ALL(dist),-1);dist[src]=0;
		int qt=0;q[qt++]=src;
		for(int qh=0;qh<qt;qh++){
			int u=q[qh];
			fore(i,0,SZ(g[u])){
				edge &e=g[u][i];int v=g[u][i].to;
				if(dist[v]<0&&e.f<e.cap)dist[v]=dist[u]+1,q[qt++]=v;
			}
		}
		return dist[dst]>=0;
	}
	ll dinic_dfs(int u, ll f){
		if(u==dst)return f;
		for(int &i=work[u];i<SZ(g[u]);i++){
			edge &e=g[u][i];
			if(e.cap<=e.f)continue;
			int v=e.to;
			if(dist[v]==dist[u]+1){
				ll df=dinic_dfs(v,min(f,e.cap-e.f));
				if(df>0){e.f+=df;g[v][e.rev].f-=df;return df;}
			}
		}
		return 0;
	}
	ll max_flow(int _src, int _dst){
		src=_src;dst=_dst;
		ll result=0;
		while(dinic_bfs()){
			fill(ALL(work),0);
			while(ll delta=dinic_dfs(src, INF))result+=delta;
		}
		return result;
	}
};

int main() {
  int n, m, s, b, k;
  cin >> n >> m;

  fore(i, 0, n) fore(j, 0, n) d[i][j] = 1000;
  fore(i, 0, m) {
    int u, v; cin >> u >> v; u--, v--;
    d[u][v] = d[v][u] = 1;
  }
  floyd(n);
  cin >> s >> b >> k;
  vector<ship> ships;
  vector<node> nodes(n);
  fore(i, 0, s) {
    int x, a, f, p; cin >> x >> a >> f >> p; x--;
    ships.pb({x, a, min(200, f), p});
  }
  fore(i, 0, b) {
    int x, d, g; cin >> x >> d >> g; x--;
    nodes[x].add({x, d, g});
  }
  fore(i, 0, n) nodes[i].prepare();
  mset(gain, -1); fore(i, 0, s) {
    fore(j, 0, n) if(d[ships[i].x][j] <= ships[i].f) {
      gain[i] = max(gain[i], nodes[j].query(ships[i].a));
    }
  }
  Dinic d(s + 2);
  ll tot = 0;
  fore(i, 0, s) {
    if(gain[i] == -1) { // really bad
      d.add_edge(i, s + 1, 1e18);
    } else {
      ll g = gain[i] - ships[i].p;
      if(g > 0) d.add_edge(s, i, g), tot += g;
      else d.add_edge(i, s + 1, -g);
    }
  }
  fore(i, 0, k) {
    int s, t; cin >> s >> t; s--, t--;
    d.add_edge(s, t, INF);
  }
  cout << tot - d.max_flow(s, s + 1) << endl;
  return 0;
}
/*
2 0
3 2 2
1 1 1 10
2 1 1 0
2 1 1 0
1 1 0
2 1 7
2 1
3 1

*/

// luogu remote judge
#include<bits/stdc++.h>
using namespace std;
using ll=long long;
class flow{
private:
int n;
vector<int>head,d,cur;
vector<tuple<int,ll,int>>edge;
bool bfs(int s,int t){
    d.assign(n,-1);
    queue<int>que;
    que.push(s);
    d[s]=0;
    while(!que.empty()){
        int u=que.front();
        que.pop();
        for(int i=head[u];i!=-1;i=get<2>(edge[i])){
            int v=get<0>(edge[i]);
            if(get<1>(edge[i])&&d[v]==-1){
                d[v]=d[u]+1;
                if(v==t){
                    return true;
                }
                que.push(v);
            }
        }
    }
    return false;
}
ll dfs(int u,int t,ll f){
    if(u==t){
        return f;
    }
    ll res=f;
    for(int &i=cur[u];i!=-1&&res;i=get<2>(edge[i])){
        int v=get<0>(edge[i]);
        ll &c=get<1>(edge[i]);
        if(d[v]==d[u]+1&&c){
            ll aug=dfs(v,t,min(res,c));
            res-=aug;
            c-=aug;
            get<1>(edge[i^1])+=aug;
        }
    }
    return f-res;
}
public:
flow(int _n){
    n=_n;
    head.assign(n,-1);
}
void insert_edge(int u,int v,ll c){
    edge.emplace_back(v,c,head[u]);
    head[u]=edge.size()-1;
    edge.emplace_back(u,0,head[v]);
    head[v]=edge.size()-1;
}
ll max_flow(int s,int t){
    ll flow=0;
    while(bfs(s,t)){
        cur=head;
        flow+=dfs(s,t,1e18);
    }
    return flow;
}
};
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int n,m;
    cin>>n>>m;
    vector<vector<int>>dis(n,vector<int>(n,1e9));
    for(int i=0;i<n;++i){
        dis[i][i]=0;
    }
    for(int i=0;i<m;++i){
        int u,v;
        cin>>u>>v;
        --u;
        --v;
        dis[u][v]=1;
        dis[v][u]=1;
    }
    for(int k=0;k<n;++k){
        for(int i=0;i<n;++i){
            for(int j=0;j<n;++j){
                dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
            }
        }
    }
    int s,b,k;
    cin>>s>>b>>k;
    vector<tuple<int,int,int,int>>ship;
    vector<vector<pair<int,int>>>base(n);
    for(int i=0;i<s;++i){
        int x,a,f,p;
        cin>>x>>a>>f>>p;
        --x;
        ship.emplace_back(x,a,f,p);
    }
    for(int i=0;i<b;++i){
        int x,d,g;
        cin>>x>>d>>g;
        --x;
        base[x].emplace_back(d,g);
    }
    for(int i=0;i<n;++i){
        sort(base[i].begin(),base[i].end());
        for(int j=1;j<base[i].size();++j){
            base[i][j].second=max(base[i][j].second,base[i][j-1].second);
        }
    }
    vector<ll>gain(s);
    for(int i=0;i<s;++i){
        int x=get<0>(ship[i]);
        int a=get<1>(ship[i]);
        int f=get<2>(ship[i]);
        int p=get<3>(ship[i]);
        gain[i]=-1e14;
        for(int j=0;j<n;++j){
            if(dis[x][j]<=f&&!base[j].empty()&&a>=base[j][0].first){
                gain[i]=max(gain[i],1ll*(--upper_bound(base[j].begin(),base[j].end(),make_pair(a,(int)1e9)))->second-p);
            }
        }
    }
    vector<bool>used(s);
    vector<pair<int,int>>rel;
    for(int i=0;i<k;++i){
        int x,y;
        cin>>x>>y;
        --x;
        --y;
        used[x]=true;
        used[y]=true;
        rel.emplace_back(x,y);
    }
    int cnt=0;
    ll ans=0;
    vector<int>id(s,-1);
    for(int i=0;i<s;++i){
        if(used[i]){
            id[i]=cnt++;
        }else if(gain[i]>0){
            ans+=gain[i];
        }
    }
    flow G(cnt+2);
    int S=cnt;
    int T=cnt+1;
    for(int i=0;i<s;++i){
        if(used[i]){
            if(gain[i]>0){
                G.insert_edge(S,id[i],gain[i]);
                ans+=gain[i];
            }else if(gain[i]<0){
                G.insert_edge(id[i],T,-gain[i]);
            }
        }
    }
    for(int i=0;i<k;++i){
        G.insert_edge(id[rel[i].first],id[rel[i].second],1e18);
    }
    ans-=G.max_flow(S,T);
    cout<<ans<<endl;
    return 0;
}

#include<bits/stdc++.h>
using namespace std;
using ll=long long;
class flow{
private:
int n;
vector<int>head,d,cur;
vector<tuple<int,ll,int>>edge;
bool bfs(int s,int t){
    d.assign(n,-1);
    queue<int>que;
    que.push(s);
    d[s]=0;
    while(!que.empty()){
        int u=que.front();
        que.pop();
        for(int i=head[u];i!=-1;i=get<2>(edge[i])){
            int v=get<0>(edge[i]);
            if(get<1>(edge[i])&&d[v]==-1){
                d[v]=d[u]+1;
                if(v==t){
                    return true;
                }
                que.push(v);
            }
        }
    }
    return false;
}
ll dfs(int u,int t,ll f){
    if(u==t){
        return f;
    }
    ll res=f;
    for(int &i=cur[u];i!=-1&&res;i=get<2>(edge[i])){
        int v=get<0>(edge[i]);
        ll &c=get<1>(edge[i]);
        if(d[v]==d[u]+1&&c){
            ll aug=dfs(v,t,min(res,c));
            res-=aug;
            c-=aug;
            get<1>(edge[i^1])+=aug;
        }
    }
    return f-res;
}
public:
flow(int _n){
    n=_n;
    head.assign(n,-1);
}
void insert_edge(int u,int v,ll c){
    edge.emplace_back(v,c,head[u]);
    head[u]=edge.size()-1;
    edge.emplace_back(u,0,head[v]);
    head[v]=edge.size()-1;
}
ll max_flow(int s,int t){
    ll flow=0;
    while(bfs(s,t)){
        cur=head;
        flow+=dfs(s,t,1e18);
    }
    return flow;
}
};
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int n,m;
    cin>>n>>m;
    vector<vector<int>>dis(n,vector<int>(n,1e9));
    for(int i=0;i<n;++i){
        dis[i][i]=0;
    }
    for(int i=0;i<m;++i){
        int u,v;
        cin>>u>>v;
        --u;
        --v;
        dis[u][v]=1;
        dis[v][u]=1;
    }
    for(int k=0;k<n;++k){
        for(int i=0;i<n;++i){
            for(int j=0;j<n;++j){
                dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
            }
        }
    }
    int s,b,k;
    cin>>s>>b>>k;
    vector<tuple<int,int,int,int>>ship;
    vector<vector<pair<int,int>>>base(n);
    for(int i=0;i<s;++i){
        int x,a,f,p;
        cin>>x>>a>>f>>p;
        --x;
        ship.emplace_back(x,a,f,p);
    }
    for(int i=0;i<b;++i){
        int x,d,g;
        cin>>x>>d>>g;
        --x;
        base[x].emplace_back(d,g);
    }
    for(int i=0;i<n;++i){
        sort(base[i].begin(),base[i].end());
        for(int j=1;j<base[i].size();++j){
            base[i][j].second=max(base[i][j].second,base[i][j-1].second);
        }
    }
    vector<ll>gain(s);
    for(int i=0;i<s;++i){
        int x=get<0>(ship[i]);
        int a=get<1>(ship[i]);
        int f=get<2>(ship[i]);
        int p=get<3>(ship[i]);
        gain[i]=-1e14;
        for(int j=0;j<n;++j){
            if(dis[x][j]<=f&&!base[j].empty()&&a>=base[j][0].first){
                gain[i]=max(gain[i],1ll*(--upper_bound(base[j].begin(),base[j].end(),make_pair(a,(int)1e9)))->second-p);
            }
        }
    }
    vector<bool>used(s);
    vector<pair<int,int>>rel;
    for(int i=0;i<k;++i){
        int x,y;
        cin>>x>>y;
        --x;
        --y;
        used[x]=true;
        used[y]=true;
        rel.emplace_back(x,y);
    }
    int cnt=0;
    ll ans=0;
    vector<int>id(s,-1);
    for(int i=0;i<s;++i){
        if(used[i]){
            id[i]=cnt++;
        }else if(gain[i]>0){
            ans+=gain[i];
        }
    }
    flow G(cnt+2);
    int S=cnt;
    int T=cnt+1;
    for(int i=0;i<s;++i){
        if(used[i]){
            if(gain[i]>0){
                G.insert_edge(S,id[i],gain[i]);
                ans+=gain[i];
            }else if(gain[i]<0){
                G.insert_edge(id[i],T,-gain[i]);
            }
        }
    }
    for(int i=0;i<k;++i){
        G.insert_edge(id[rel[i].first],id[rel[i].second],1e18);
    }
    ans-=G.max_flow(S,T);
    cout<<ans<<endl;
    return 0;
}

#include<iostream>
#include<string>
#include<cstdio>
#include<vector>
#include<cmath>
#include<algorithm>
#include<functional>
#include<iomanip>
#include<queue>
#include<ciso646>
#include<random>
#include<map>
#include<set>
#include<bitset>
#include<stack>
#include<unordered_map>
#include<utility>
#include<cassert>
using namespace std;

typedef long long ll;

typedef unsigned long long ul;
typedef unsigned int ui;
const ll mod = 1000000007;
const ll INF = 100000000000000;
typedef pair<int, int> P;
#define stop char nyaa;cin>>nyaa;
#define rep(i,n) for(int i=0;i<n;i++)
#define per(i,n) for(int i=n-1;i>=0;i--)
#define Rep(i,sta,n) for(int i=sta;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define per1(i,n) for(int i=n;i>=1;i--)
#define Rep1(i,sta,n) for(int i=sta;i<=n;i++)
typedef pair<ll, ll> LP;
typedef vector<int> vec;
typedef vector<string> svec;
typedef long double ld;
typedef pair<ld, ld> LDP;
const ld eps = 1e-8;
#include<cstring>
struct edge { int to; ll cap;int rev; };
vector<edge> G[100000];
bool used[100000];
void add_edge(int from, int to, ll cap) {
	G[from].push_back(edge{ to, cap, (int)G[to].size() });
	G[to].push_back(edge{ from, 0, (int)G[from].size() - 1 });
}
ll dfs(int v, int t, ll f) {
	if (v == t)return f;
	used[v] = true;
	for (int i = 0; i < (int)G[v].size(); i++) {
		edge &e = G[v][i];
		if (!used[e.to] && e.cap > 0) {
			int d = dfs(e.to, t, min(f, e.cap));
			if (d > 0) {
				e.cap -= d;
				G[e.to][e.rev].cap += d;
				return d;
			}
		}
	}
	return 0;
}
ll max_flow(int s, int t) {
	ll flow = 0;
	for (;;) {
		memset(used, 0, sizeof(used));
		ll f = dfs(s, t, INF);
		if (f == 0)return flow;
		flow += f;
	}
}

int distr[101][101];
void solve() {
	int n, m; cin >> n >> m;
	rep(i, n) {
		rep(j, n) {
			if (i == j)distr[i][j] = 0;
			else distr[i][j] = mod;
		}
	}
	rep(i, m) {
		int a, b; cin >> a >> b; a--; b--;
		distr[a][b] = distr[b][a] = 1;
	}
	rep(k, n) {
		rep(i, n) {
			rep(j, n) {
				distr[i][j] = min(distr[i][j], distr[i][k] + distr[k][j]);
			}
		}
	}
	int nl, nr, nrel; cin >> nl >> nr >> nrel;
	vector<int> xl(nl), a(nl), f(nl), p(nl);
	vector<int> xr(nr), b(nr), g(nr);
	rep(i, nl) {
		cin >> xl[i] >> a[i] >> f[i] >> p[i]; xl[i]--;
	}
	rep(i, nr) {
		cin >> xr[i] >> b[i] >> g[i]; xr[i]--;
	}
	vector<P> rel(nrel);
	rep(i, nrel) {
		int u, v; cin >> u >> v; u--; v--;
		rel[i] = { u,v };
	}
	vector<vector<P>> vb(n);
	rep(i, nr) {
		vb[xr[i]].push_back({ b[i],g[i] });
	}
	vector<vector<int>> bb(n), hg(n);
	rep(i, n) {
		sort(vb[i].begin(), vb[i].end());
		bb[i].resize(vb[i].size());
		hg[i].resize(vb[i].size()+1);
		int ma = -2*mod;
		rep(j, (int)vb[i].size()) {
			bb[i][j] = vb[i][j].first;
			hg[i][j] = ma;
			ma = max(ma, vb[i][j].second);
		}
		hg[i][vb[i].size()] = ma;
	}
	vector<bool> cant(nl,false);
	vector<ll> val(nl);
	rep(i, nl) {
		int maval = -2*mod;
		rep(j, n) {
			int d = distr[xl[i]][j];
			if (d > f[i])continue;
			int id = upper_bound(bb[j].begin(), bb[j].end(), a[i]) - bb[j].begin();
			maval = max(maval, hg[j][id]);
		}
		if (maval == -2 * mod) {
			cant[i] = true;
		}
		val[i] = (ll)maval - (ll)p[i];
		//cout << "hello" << endl;
		//cout << i << " " << val[i] << endl;
	}
	vector<bool> exi(nl,false);
	rep(i, nrel) {
		int u = rel[i].first, v = rel[i].second;
		exi[u] = exi[v] = true;
	}
	vector<int> ids;
	vector<int> trans(nl);
	ll ans = 0;
	rep(i, nl) {
		if (!exi[i]) {
			ans += max((ll)0, val[i]);
		}
		else {
			trans[i] = ids.size();
			ids.push_back(i);
		}
	}
	int s = ids.size(); int t = s + 1;
	rep(i, ids.size()) {
		int id = ids[i];
		ll cost = val[id];
		if (cost < 0) {
			add_edge(s, i,-cost);
			add_edge(i, t, 0);
		}
		else {
			add_edge(s, i, 0);
			add_edge(i, t, cost);
		}
		if (cant[id]) {
			add_edge(s, i, INF);
		}
	}
	rep(i, nrel) {
		int u = rel[i].first, v = rel[i].second;
		u = trans[u], v = trans[v];
		add_edge(v, u, INF);
	}
	ll sum = 0;
	rep(i, ids.size()) {
		if (val[ids[i]] >= 0) {
			sum += val[ids[i]];
		}
	}
	ll z = max_flow(s, t);
	//cout << z << endl;
	sum -= z;
	ans += sum;
	cout << ans << endl;
}

signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);

	solve();
	//stop
	return 0;
}

#include<bits/stdc++.h>
using namespace std;

const int MAXN=3000+5,MAXM=10000+10;
const long long int INF = 1e15;
bool visit[MAXN];
int head[MAXN],dist[MAXN],stamp,tmphead[MAXN];
struct EDGE{
   int to;
   long long int r;
   int next;
}edge[MAXM*2];
void init(){
   stamp=0;
   memset(head,-1,sizeof head);
}
void addedge(int a,int b,long long int c){
   edge[stamp]={b,c,head[a]};
   head[a]=stamp++;
   edge[stamp]={a,0,head[b]};
   head[b]=stamp++;
}
int BFS(int s,int t){
   for(int i=0;i<=t;i++)//The nodes being used
      dist[i]=1e9;
   memset(visit,0,sizeof visit);
   queue<int> q;
   q.push(s);dist[s]=0;visit[s]=true;
   while(!q.empty()){
      int now=q.front();q.pop();
      for(int i=head[now];i!=-1;i=edge[i].next){
         int nextnode=edge[i].to;
         if(edge[i].r>0&&!visit[nextnode]){
            dist[nextnode]=dist[now]+1;
            visit[nextnode]=true;
            q.push(nextnode);
            if(nextnode==t)   return dist[t];
         }
      }
   }
   return -1;
}
long long int DFS(int now,long long int df,int t){
   if(now==t)  return df;
   visit[now]=true;
   for(int i=tmphead[now];i!=-1;tmphead[now]=i=edge[i].next){
      int nextnode=edge[i].to;
      if(edge[i].r>0&&dist[now]+1==dist[nextnode]&&!visit[nextnode]){
         long long int f=DFS(nextnode,min(df,edge[i].r),t);
         if(f){
            edge[i].r-=f;
            edge[i^1].r+=f;
            return f;
         }
      }
   }
   return 0;
}
long long int Dinic(int s,int t){
   long long int flow=0;
   while(BFS(s,t)!=-1){
      memcpy(tmphead,head,sizeof head);
      while(true){
         memset(visit,0,sizeof visit);
         long long int f=DFS(s,INF,t);
         if(!f)   break;
         flow+=f;
      }
   }
   return flow;
}

int dp[101][101];
struct SP{
	int x,a,f,p,pro,idx;
	bool operator<(const SP& rhs)const{
		return a<rhs.a;
	}
}sp[100001];

struct BA{
	int x,d,g;
	bool operator<(const BA& rhs)const{
		return d<rhs.d;
	}
}ba[100001];
int cur[101];
int s1[1001],s2[1001];
map<int,int> mp;
set<int> st;
int main(){
	ios_base::sync_with_stdio(0);
	cin.tie(0);
	int n,m;
	cin>>n>>m;
	init();
	for(int i=1;i<=100;i++)
		cur[i]=-1e9-1;
	for(int i=1;i<=100;i++)
		for(int j=1;j<=100;j++)
			dp[i][j]=1e9+1;
	for(int i=1,u,v;i<=m;i++){
		cin>>u>>v;
		dp[u][v]=dp[v][u]=1;
	}
	for(int i=1;i<=100;i++)
		dp[i][i]=0;
	for(int k=1;k<=n;k++)
		for(int i=1;i<=n;i++)
			for(int j=1;j<=n;j++)
				dp[i][j]=min(dp[i][j],dp[i][k]+dp[k][j]);
	int s,b,k;
	cin>>s>>b>>k;
	for(int i=1;i<=s;i++){
		cin>>sp[i].x>>sp[i].a>>sp[i].f>>sp[i].p;
		sp[i].pro=-1e9-1;
		sp[i].idx=i;
	}
	sort(sp+1,sp+s+1);
	for(int i=1;i<=b;i++){
		cin>>ba[i].x>>ba[i].d>>ba[i].g;
	}
	sort(ba+1,ba+b+1);
	int pb=1;
	for(int i=1;i<=s;i++){
		while(pb<=b&&ba[pb].d<=sp[i].a)
			cur[ba[pb].x]=max(cur[ba[pb].x],ba[pb].g),pb++;
		for(int j=1;j<=n;j++)
			if(dp[j][sp[i].x]<=sp[i].f)
				sp[i].pro=max(sp[i].pro,cur[j]);
	}
	for(int i=1;i<=k;i++){
		cin>>s1[i]>>s2[i];
		st.insert(s1[i]);st.insert(s2[i]);
	}
	int stp=0;
	for(int it:st)
		mp[it]=++stp;
	long long int ans=0;
	for(int i=1;i<=s;i++){
		sp[i].pro-=sp[i].p;
		if(sp[i].pro>=0)	ans+=sp[i].pro;
		if(mp.find(sp[i].idx)!=mp.end()){
			if(sp[i].pro>0)
				addedge(stp+1,mp[sp[i].idx],sp[i].pro);
			else if(sp[i].pro<0)
					addedge(mp[sp[i].idx],stp+2,(sp[i].pro<-1e9?INF:-sp[i].pro));
		}
	}
	for(int i=1;i<=k;i++)
		addedge(mp[s1[i]],mp[s2[i]],INF);
	cout<<ans-Dinic(stp+1,stp+2)<<endl;
}

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>

#pragma GCC optimize("Ofast,no-stack-protector")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,sse4.1,sse4.2,popcnt,avx,avx2,abm,mmx,tune=native")

using namespace __gnu_pbds;
using namespace std;

#define mp make_pair
#define sz(x) (int)((x).size())
#define all(x) (x).begin(),(x).end()
#define FO(x) {freopen(#x".in","r",stdin);freopen(#x".out","w",stdout);}
#define eb emplace_back

typedef pair< int, int > pii;
typedef pair< long long, long long > pll;
typedef long long ll;
typedef unsigned long long ull;
typedef vector< int > vi;
typedef vector< vi > vvi;
typedef vector< ll > vll;
typedef vector< vll > vvll;
typedef vector< pii > vpii;
typedef vector< vpii > vvpii;
typedef vector< pll > vpll;
typedef long double ld;
typedef vector< ld > vld;

const ll MOD = 1e9 + 7;

const ull infull = numeric_limits<unsigned long long>::max();

void fix(int &x, ll MOD) {
    x = (x % MOD);
    if(x < 0) x += MOD;
    return;
}

ll lgput(ll a, ll b, ll MOD) {
    ll ret = 1;
    a %= MOD;
    while(b) {
        if(b&1) ret = ret*a % MOD;
        a = a*a % MOD;
        b >>= 1;
    }

    return ret;
}

ll inv(ll a, ll MOD) {
    return lgput(a, MOD-2, MOD);
}

struct f {
    int a, b;
    f(int _a = 0, int _b = 0) : a(_a) ,b(_b) {}
    ll eval(int x) {
        return 1ll*x*a + b;
    }
};

int binarySearch(int x, vi &v) {
    int pos = 0;
    int l = 1, r = sz(v);
    while(l <= r) {
        int m = l + r >> 1;
        if(v[m] <= x) {
            pos = m;
            l = m + 1;
        } else {
            r = m - 1;
        }
    }

    return pos;
}

using Matrix = vvi;

Matrix mult(Matrix a, Matrix b) {
    assert(a[0].size() == b.size());

    Matrix ret(a.size(), vector< int >(b[0].size()));

    for(int i = 0; i < a.size(); ++i) {
        for(int j = 0; j < b[0].size(); ++j) {
            for(int k = 0; k < a[0].size(); ++k) {
                ret[i][j] += ((1ll*a[i][k]*b[k][j])%MOD);
                if(ret[i][j] >= MOD) ret[i][j] -= MOD;
            }
        }
    }

    return ret;
}

typedef ll i64;

struct Dinic {
    struct Edge {
        i64 flow;
        int to, next;
    };
    vector<Edge> edges;
    vector<int> adia, at, dist;
    int S, D;
    void add_Edge(int from, int to, i64 cap) {
        edges.push_back({ cap, to, adia[from] });
        adia[from] = edges.size() - 1;
        edges.push_back({ 0, from, adia[to] });
        adia[to] = edges.size() - 1;
    }
    bool bfs() {
        queue<int> q;
        fill(dist.begin(), dist.end(), 1e9);
        dist[S] = 0;
        q.push(S);
        while (!q.empty()) {
            int x = q.front();
            q.pop();
            for (int i = adia[x]; i != -1; i = edges[i].next) {
                if (dist[edges[i].to] > dist[x] + 1 && edges[i].flow) {
                    dist[edges[i].to] = 1 + dist[x];
                    q.push(edges[i].to);
                }
            }
        }
        return dist[D] < 1e9;
    }
    i64 dfs(int nod, i64 fmax) {
        if (nod == D)
            return fmax;
        while (at[nod] != -1) {
            Edge& e = edges[at[nod]];
            i64 f;
            if (dist[e.to] == dist[nod] + 1 && e.flow
                && (f = dfs(e.to, min(fmax, e.flow)))) {
                e.flow -= f;
                edges[at[nod] ^ 1].flow += f;
                return f;
            }
            at[nod] = edges[at[nod]].next;
        }
        return 0;
    }
    i64 GetFlow() {
        i64 f = 0;
        while (bfs()) {
            at = adia;
            while (i64 x = dfs(S, 1e18))
                f += x;
        }
        return f;
    }
    Dinic(int n = 0, int s = 0, int d = 0) {
        S = s, D = d;
        at = dist = adia = vector<int>(n + 1, -1);
    }
};

int main() {
    #ifdef BLAT
        freopen("stdin", "r", stdin);
        freopen("stderr", "w", stderr);
    #endif

    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cout.precision(12);
    srand(time(NULL));

    int n, m;
    cin >> n >> m;

    vvi dist(n + 1, vi(n + 1, 1e9));

    for(int i = 1, a, b; i <= m; ++i) {
        cin >> a >> b;
        dist[a][b] = dist[b][a] = 1;
    }

    for(int i = 1; i <= n; ++i) dist[i][i] = 1;

    for(int k = 1; k <= n; ++k) {
        for(int i = 1; i <= n; ++i) {
            for(int j = 1; j <= n; ++j) {
                dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
            }
        }
    }

    int s, b, k;
    cin >> s >> b >> k;

    vi locAtt(s + 1), att(s + 1), fuel(s + 1), price(s + 1);

    for(int i = 1; i <= s; ++i) {
        cin >> locAtt[i] >> att[i] >> fuel[i] >> price[i];
    }

    vi locDef(b + 1), def(b + 1), gold(b + 1);

    for(int i = 1; i <= b; ++i) {
        cin >> locDef[i] >> def[i] >> gold[i];
    }

    vpii dependecies(k + 1);
    for(int i = 1; i <= k; ++i) {
        cin >> dependecies[i].first >> dependecies[i].second;
    }

    vll profit(s + 1, -1e18);

    for(int i = 1; i <= n; ++i) {
        struct str {
            int type, p, ind;
            str(int _type = 0, int _p = 0, int _ind = 0) : type(_type), p(_p), ind(_ind) {}
        };

        vector< str > v;

        for(int j = 1; j <= b; ++j) {
            if(locDef[j] == i) v.emplace_back(1, def[j], j);
        }

        for(int j = 1; j <= s; ++j) {
            if(dist[i][locAtt[j]] <= fuel[j]) v.emplace_back(0, att[j], j);
        }

        sort(all(v), [&](str &a, str &b) -> bool {
            if(a.p == b.p) return a.type > b.type;
            return a.p < b.p;
        });

        long long curMax = -1e18;
        for(auto &x : v) {
            if(x.type == 1) {
                curMax = max(curMax, (ll)gold[x.ind]);
            } else {
                profit[x.ind] = max(profit[x.ind], curMax - price[x.ind]);
            }
        }
    }

    long long ans = 0;
    for(int i = 1; i <= s; ++i) {
        if(profit[i] > 0) ans += profit[i];
    }

    vector< int > flowNodes;
    for(int i = 1; i <= k; ++i) {
        auto x = dependecies[i];
        flowNodes.emplace_back(x.first);
        flowNodes.emplace_back(x.second);
    }

    sort(all(flowNodes));
    flowNodes.erase(unique(all(flowNodes)), flowNodes.end());

    vector< int > actualIndex(s + 1);
    for(int i = 0; i < flowNodes.size(); ++i) {
        actualIndex[flowNodes[i]] = i + 1;
    }

    const int source = 0;
    const int target = flowNodes.size() + 1;

    vector< int > lvl(target + 1);
    vvll curFlow(target + 1, vll(target + 1));
    vvll cap(target + 1, vll(target + 1));
    vvi gr(target + 1);

    Dinic flow(target + 1, source, target);

    for(int i = 1; i <= k; ++i) {
        auto x = dependecies[i];
        flow.add_Edge(actualIndex[x.second], actualIndex[x.first], 1e18);
    }

    for(int i = 0; i < flowNodes.size(); ++i) {
        if(profit[flowNodes[i]] < 0) {
            flow.add_Edge(source, i + 1, -profit[flowNodes[i]]);
        } else {
            flow.add_Edge(i + 1, target, profit[flowNodes[i]]);
        }
    }

    cout << ans - flow.GetFlow() << '\n';
    return 0;
}

#pragma comment(linker, "/stack:200000000")
#pragma GCC optimize("Ofast")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")

#include <iostream>
#include <vector>
#include <tuple>
#include <algorithm>
#include <queue>
using namespace std;
using Graph = vector<vector<int>>;
using ll = long long;
const ll INF = 1e18;

struct MaxFlow {
	struct edge {
		int a, b;
		ll c;
	};
	vector<edge> es;
	vector<vector<int> > g;
	vector<int> d, pt;
	MaxFlow(int n) : g(n+1), d(n+1), pt(n+1) {}
	void addEdge(int a, int b, ll c) {
		es.push_back({a, b, c});
		g[a].push_back((int)es.size()-1);
		es.push_back({b, a, 0});
		g[b].push_back((int)es.size()-1);
	}
	bool bfs(int source, int sink) {
		queue<int> q({source});
		fill(d.begin(), d.end(), (int)g.size()+1);
		d[source]=0;
		while(!q.empty()) {
			int x=q.front();q.pop();
			if (x==sink) break;
			for (int k:g[x]) {
				edge& e=es[k];
				if (e.c>0&&d[e.b]>d[e.a]+1) {
					d[e.b]=d[e.a]+1;
					q.push(e.b);
				}
			}
		}
		return d[sink]!=(int)g.size()+1;
	}
	ll flow(int x, int sink, ll fl=INF) {
		if (x==sink||fl==0) return fl;
		for (int& i=pt[x];i<(int)g[x].size();i++) {
			edge& e=es[g[x][i]];
			edge& oe=es[g[x][i]^1];
			if (d[e.b]==d[e.a]+1) {
				if (ll pf=flow(e.b, sink, min(e.c, fl))) {
					e.c-=pf;
					oe.c+=pf;
					return pf;
				}
			}
		}
		return 0;
	}
	ll getMaxFlow(int source, int sink) {
		ll r=0;
		while (bfs(source, sink)) {
			fill(pt.begin(), pt.end(), 0);
			while (ll t=flow(source, sink)) r+=t;
		}
		return r;
	}
};

ll solve(const Graph& g, const vector<ll>& vals) {
	// Problem is equivalent to:
	// 	maximize v1 x1 + ... + vn xn
	// 	subject to
	// 		xi - xj <= 0 if j \in g[i]
	// 		0 <= xi <= 1

	// Dual:
	// 	minimize y1 + ... + yn
	// 	subject to
	// 		yi + \sum_{outs} r_{j} >= vi + \sum_{ins} r_{j}
	// 		0 <= yi, rj

	// Use max-flow. r_{j} is flow along edge j. We have
	// 	yi + \sum_{outs} r_{j} >= vi + \sum_{ins} r_{j} (if vi >= 0)
	//	yi + \sum_{outs} r_{j} - vi >= \sum_{ins} r_{j} (if vi < 0)

	int n = g.size();
	int source = n;
	int sink = n+1;

	ll res = 0;
	MaxFlow dinic(n+2);
	for (int i = 0; i < n; ++i) {
		if (vals[i] < 0) {
			dinic.addEdge(i, sink, -vals[i]);
		} else {
			dinic.addEdge(source, i, vals[i]);
			res += vals[i];
		}
		for (auto t : g[i]) {
			dinic.addEdge(i, t, INF);
		}
	}
	res -= dinic.getMaxFlow(source, sink);
	return res;
}

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(0);

	int n, m;
	cin >> n >> m;
	vector<vector<ll>> dist(n);
	for (int i = 0; i < n; ++i) {
		dist[i].resize(n, INF);
		dist[i][i] = 0;
	}

	for (int i = 0; i < m; ++i) {
		int a, b;
		cin >> a >> b;
		--a; --b;
		dist[a][b] = 1;
		dist[b][a] = 1;
	}
	for (int i = 0; i < n; ++i) {
		for (int a = 0; a < n; ++a) {
			for (int b = 0; b < n; ++b) {
				dist[a][b] = min(dist[a][b], dist[a][i] + dist[i][b]);
			}
		}
	}

	int s, b, k;
	cin >> s >> b >> k;

	vector<tuple<int, int, int, int>> ships(s);
	for (int i = 0; i < s; ++i) {
		int loc, atk, fuel, cost;
		cin >> loc >> atk >> fuel >> cost;
		--loc;
		ships[i] = tie(loc, atk, fuel, cost);
	}
	vector<tuple<int, int, int>> bases(b);
	for (int i = 0; i < b; ++i) {
		int tar, def, gold;
		cin >> tar >> def >> gold;
		--tar;
		bases[i] = tie(tar, def, gold);
	}
	sort(bases.begin(), bases.end());

	vector<vector<pair<int, int>>> offs(n);
	for (int i = 0; i < b; ++i) {
		int tar, def, gold;
		tie(tar, def, gold) = bases[i];
		if (offs[tar].empty() || offs[tar].back().second < gold) {
			offs[tar].push_back({def, gold});
		}
	}

	vector<ll> vals(s, -INF);
	for (int i = 0; i < s; ++i) {
		int loc, atk, fuel, cost;
		tie(loc, atk, fuel, cost) = ships[i];

		for (int t = 0; t < n; ++t) {
			if (dist[loc][t] > fuel) continue;
			int low = -1;
			int high = (int)offs[t].size() - 1;
			while(low != high) {
				int mid = (low + high + 1) >> 1;
				if (atk >= offs[t][mid].first) low = mid;
				else high = mid - 1;
			}
			if (low >= 0) vals[i] = max(vals[i], (ll)offs[t][low].second);
		}
		vals[i] -= cost;
	}

	Graph g(s);
	for (int j = 0; j < k; ++j) {
		int x, y;
		cin >> x >> y;
		--x; --y;
		g[x].push_back(y);
	}

	ll res = solve(g, vals);
	cout << res << '\n';
}

#pragma GCC optimize("Ofast")
#include <iostream>
#include <vector>
#include <tuple>
#include <algorithm>
#include <queue>
using namespace std;
using Graph = vector<vector<int>>;
using ll = long long;
const ll INF = 1e18;

// Dinic's algorithm for max flow
// Source must be node 0, sink must be node n-1
// All edges are directed
// O(V^2 E) in general
// O(min(V^{2/3}, sqrt{E}) E) in graphs with unit capacities
// O(sqrt{V} E) in unit networks (e.g. bipartite matching)
class Dinic {
	private:
		constexpr static ll INF = 8*(ll)1e18;
		struct Edge {
			const int s, t;
			const ll c; // capacity
			ll f; // flow

			Edge(int src, int tar, ll cap = INF, bool dir = 1)
				: s(src), t(tar), c(dir ? cap : 2*cap), f(dir ? 0 : cap) {}

			int getOth(int i) { return i == s ? t : s; }
			ll getCap(int i) { return i == s ? c - f : f; }
			void push(int i, ll am) { f += (i == s ? am : -am); }
		};

		const int source, sink, n;
		vector<Edge> edges;
		vector<vector<int>> conns;
		vector<int> dist;
		vector<bool> done;

		bool calcDists() {
			for (int i = 0; i < n; ++i) dist[i] = n;
			dist[sink] = 0;
			vector<int> que = {sink};
			for (int j = 0; j < que.size(); ++j) {
				int i = que[j];
				for (auto ei : conns[i]) {
					int t = edges[ei].getOth(i);
					if (edges[ei].getCap(t) == 0) continue;
					if (dist[t] == n) {
						dist[t] = dist[i] + 1;
						que.push_back(t);
					}
				}
			}
			return dist[source] < n;
		}
		ll dfsFlow(int i, ll cap = INF) {
			if (i == sink) return cap;
			ll res = 0;
			for (auto ei : conns[i]) {
				int t = edges[ei].getOth(i);
				if (done[t] || dist[t] != dist[i] - 1) continue;

				ll subcap = min(cap-res, edges[ei].getCap(i));
				if (subcap == 0) {
					if (cap == res) return res;
				} else {
					ll add = dfsFlow(t, subcap);
					res += add;
					edges[ei].push(i, add);
				}
			}
			if (res < cap) done[i] = true;
			return res;
		}
	public:
		Dinic(int nn, int s, int t)
			: n(nn), conns(nn), dist(nn), done(nn), source(s), sink(t) {}

		const Edge& getEdge(int j) const { return edges[j]; }
		void addEdge(int a, int b, ll c = INF, bool dir = 1) {
			edges.emplace_back(a, b, c, dir);
			conns[a].push_back(edges.size() - 1);
			conns[b].push_back(edges.size() - 1);
		}
		ll pushFlow() {
			ll res = 0;
			while(calcDists()) {
				for (int i = 0; i < n; ++i) done[i] = false;
				res += dfsFlow(source);
			}
			return res;
		}
};

ll solve(const Graph& g, const vector<ll>& vals) {
	// Problem is equivalent to:
	// 	maximize v1 x1 + ... + vn xn
	// 	subject to
	// 		xi - xj <= 0 if j \in g[i]
	// 		0 <= xi <= 1

	// Dual:
	// 	minimize y1 + ... + yn
	// 	subject to
	// 		yi + \sum_{outs} r_{j} >= vi + \sum_{ins} r_{j}
	// 		0 <= yi, rj

	// Use max-flow. r_{j} is flow along edge j. We have
	// 	yi + \sum_{outs} r_{j} >= vi + \sum_{ins} r_{j} (if vi >= 0)
	//	yi + \sum_{outs} r_{j} - vi >= \sum_{ins} r_{j} (if vi < 0)

	int n = g.size();
	int source = n;
	int sink = n+1;
	Dinic dinic(n+2, source, sink);

	ll res = 0;
	for (int i = 0; i < n; ++i) {
		if (vals[i] < 0) {
			dinic.addEdge(i, sink, -vals[i]);
		} else {
			dinic.addEdge(source, i, vals[i]);
			res += vals[i];
		}
		for (auto t : g[i]) {
			dinic.addEdge(i, t);
		}
	}
	res -= dinic.pushFlow();
	return res;
}

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(0);

	int n, m;
	cin >> n >> m;
	vector<vector<ll>> dist(n);
	for (int i = 0; i < n; ++i) {
		dist[i].resize(n, INF);
		dist[i][i] = 0;
	}

	for (int i = 0; i < m; ++i) {
		int a, b;
		cin >> a >> b;
		--a; --b;
		dist[a][b] = 1;
		dist[b][a] = 1;
	}
	for (int i = 0; i < n; ++i) {
		for (int a = 0; a < n; ++a) {
			for (int b = 0; b < n; ++b) {
				dist[a][b] = min(dist[a][b], dist[a][i] + dist[i][b]);
			}
		}
	}

	int s, b, k;
	cin >> s >> b >> k;

	vector<tuple<int, int, int, int>> ships(s);
	for (int i = 0; i < s; ++i) {
		int loc, atk, fuel, cost;
		cin >> loc >> atk >> fuel >> cost;
		--loc;
		ships[i] = tie(loc, atk, fuel, cost);
	}
	vector<tuple<int, int, int>> bases(b);
	for (int i = 0; i < b; ++i) {
		int tar, def, gold;
		cin >> tar >> def >> gold;
		--tar;
		bases[i] = tie(tar, def, gold);
	}
	sort(bases.begin(), bases.end());

	vector<vector<pair<int, int>>> offs(n);
	for (int i = 0; i < b; ++i) {
		int tar, def, gold;
		tie(tar, def, gold) = bases[i];
		if (offs[tar].empty() || offs[tar].back().second < gold) {
			offs[tar].push_back({def, gold});
		}
	}

	vector<ll> vals(s, -INF);
	for (int i = 0; i < s; ++i) {
		int loc, atk, fuel, cost;
		tie(loc, atk, fuel, cost) = ships[i];

		for (int t = 0; t < n; ++t) {
			if (dist[loc][t] > fuel) continue;
			int low = -1;
			int high = (int)offs[t].size() - 1;
			while(low != high) {
				int mid = (low + high + 1) >> 1;
				if (atk >= offs[t][mid].first) low = mid;
				else high = mid - 1;
			}
			if (low >= 0) vals[i] = max(vals[i], (ll)offs[t][low].second);
		}
		vals[i] -= cost;
	}

	Graph g(s);
	for (int j = 0; j < k; ++j) {
		int x, y;
		cin >> x >> y;
		--x; --y;
		g[x].push_back(y);
	}

	ll res = solve(g, vals);
	cout << res << '\n';
}

#pragma GCC optimize("Ofast")
#include <iostream>
#include <vector>
#include <tuple>
#include <algorithm>
#include <queue>
using namespace std;
using Graph = vector<vector<int>>;
using ll = long long;
const ll INF = 1e18;

// Dinic's algorithm for max flow
// O(V^2 E) in general
// O(min(V^{2/3}, E^1/2) E) in graphs with unit capacities
// O(sqrt{V} E) in unit networks (e.g. bipartite matching)
class Dinic {
	private:
		const static ll INF = 8*(ll)1e18;
		struct Edge {
			const int t; // Endpoint
			const ll c; // Capacity
			ll a; // Admissible flow
			Edge(int tar, ll cap = INF) : t(tar), c(cap), a(cap) {}
		};

		vector<Edge> edges;
		vector<vector<int>> conns;
		vector<int> dist, act_ind;

		ll push(int ei, ll v) {
			edges[ei].a -= v;
			edges[ei ^ 1].a += v;
			return v;
		}
		void calcDists(int sink) {
			for (int& v : dist) v = -1;
			dist[sink] = 0;
			vector<int> que = {sink};
			for (int j = 0; j < que.size(); ++j) {
				for (auto ei : conns[que[j]]) {
					int t = edges[ei].t;
					if (edges[ei^1].a > 0 && dist[t] == -1) {
						dist[t] = dist[que[j]] + 1;
						que.push_back(t);
					}
				}
			}
		}
		ll dfsFlow(int i, int sink, ll cap) {
			if (i == sink) return 0;
			for (int& j = act_ind[i]; j < conns[i].size(); ++j) {
				int ei = conns[i][j];
				int t = edges[ei].t;
				if (dist[t] != dist[i] - 1 || edges[ei].a == 0) continue;

				ll subcap = min(cap, edges[ei].a);
				cap -= push(ei, subcap - dfsFlow(t, sink, subcap));
				if (! cap) return 0;
			}
			return cap;
		}
	public:
		Dinic(int n) : conns(n), dist(n), act_ind(n) {}

		int addEdge(int s, int t, ll c = INF, bool dir = 1) {
			int i = edges.size() / 2;
			edges.emplace_back(t, c);
			edges.emplace_back(s, dir ? 0 : c);
			conns[s].push_back(2*i);
			conns[t].push_back(2*i+1);
			return i;
		}
		ll pushFlow(int source, int sink) {
			for (ll res = 0;;) {
				calcDists(sink);
				if (dist[source] == -1) return res;
				for (int& v : act_ind) v = 0;
				res += INF - dfsFlow(source, sink, INF);
			}
		}
		ll getFlow(int i) const { return edges[2*i].c - edges[2*i].a; }
};
ll solve(const Graph& g, const vector<ll>& vals) {
	// Problem is equivalent to:
	// 	maximize v1 x1 + ... + vn xn
	// 	subject to
	// 		xi - xj <= 0 if j \in g[i]
	// 		0 <= xi <= 1

	// Dual:
	// 	minimize y1 + ... + yn
	// 	subject to
	// 		yi + \sum_{outs} r_{j} >= vi + \sum_{ins} r_{j}
	// 		0 <= yi, rj

	// Use max-flow. r_{j} is flow along edge j. We have
	// 	yi + \sum_{outs} r_{j} >= vi + \sum_{ins} r_{j} (if vi >= 0)
	//	yi + \sum_{outs} r_{j} - vi >= \sum_{ins} r_{j} (if vi < 0)

	int n = g.size();
	int source = n;
	int sink = n+1;
	Dinic dinic(n+2);

	ll res = 0;
	for (int i = 0; i < n; ++i) {
		if (vals[i] < 0) {
			dinic.addEdge(i, sink, -vals[i]);
		} else {
			dinic.addEdge(source, i, vals[i]);
			res += vals[i];
		}
		for (auto t : g[i]) {
			dinic.addEdge(i, t);
		}
	}
	res -= dinic.pushFlow(source, sink);
	return res;
}

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(0);

	int n, m;
	cin >> n >> m;
	vector<vector<ll>> dist(n);
	for (int i = 0; i < n; ++i) {
		dist[i].resize(n, INF);
		dist[i][i] = 0;
	}

	for (int i = 0; i < m; ++i) {
		int a, b;
		cin >> a >> b;
		--a; --b;
		dist[a][b] = 1;
		dist[b][a] = 1;
	}
	for (int i = 0; i < n; ++i) {
		for (int a = 0; a < n; ++a) {
			for (int b = 0; b < n; ++b) {
				dist[a][b] = min(dist[a][b], dist[a][i] + dist[i][b]);
			}
		}
	}

	int s, b, k;
	cin >> s >> b >> k;

	vector<tuple<int, int, int, int>> ships(s);
	for (int i = 0; i < s; ++i) {
		int loc, atk, fuel, cost;
		cin >> loc >> atk >> fuel >> cost;
		--loc;
		ships[i] = tie(loc, atk, fuel, cost);
	}
	vector<tuple<int, int, int>> bases(b);
	for (int i = 0; i < b; ++i) {
		int tar, def, gold;
		cin >> tar >> def >> gold;
		--tar;
		bases[i] = tie(tar, def, gold);
	}
	sort(bases.begin(), bases.end());

	vector<vector<pair<int, int>>> offs(n);
	for (int i = 0; i < b; ++i) {
		int tar, def, gold;
		tie(tar, def, gold) = bases[i];
		if (offs[tar].empty() || offs[tar].back().second < gold) {
			offs[tar].push_back({def, gold});
		}
	}

	vector<ll> vals(s, -INF);
	for (int i = 0; i < s; ++i) {
		int loc, atk, fuel, cost;
		tie(loc, atk, fuel, cost) = ships[i];

		for (int t = 0; t < n; ++t) {
			if (dist[loc][t] > fuel) continue;
			int low = -1;
			int high = (int)offs[t].size() - 1;
			while(low != high) {
				int mid = (low + high + 1) >> 1;
				if (atk >= offs[t][mid].first) low = mid;
				else high = mid - 1;
			}
			if (low >= 0) vals[i] = max(vals[i], (ll)offs[t][low].second);
		}
		vals[i] -= cost;
	}

	Graph g(s);
	for (int j = 0; j < k; ++j) {
		int x, y;
		cin >> x >> y;
		--x; --y;
		g[x].push_back(y);
	}

	ll res = solve(g, vals);
	cout << res << '\n';
}

#pragma GCC optimize("Ofast")
/*#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("fast-math")
#pragma GCC target("sse,sse2,sse3,ssse3,popcnt,abm,mmx,tune=native")*/
#include <iostream>
#include <vector>
#include <algorithm>
#include <set>
#include <map>
#include <unordered_set>
#include <unordered_map>
#include <stdio.h>
#include <cstdio>
#include <math.h>
#include <cmath>
#include <string>
#include <cstring>
#include <queue>
#include <deque>
#include <random>
#include <iomanip>
#include <bitset>

using namespace std;

template<typename T> void uin(T &a, T b) {
    if (b < a) {
        a = b;
    }
}

template<typename T> void uax(T &a, T b) {
    if (b > a) {
        a = b;
    }
}

#define int long long
#define ghost signed
#define left left228
#define right right228
#define prev prev228
#define list list228

const int INF = 1e15;

namespace Dinic
{
	const int N = 100 * 1000 + 228;

	struct edge
	{
		int from, to, cap, flow;

		int rem() {
			return cap - flow;
		}

		edge() {}
		edge(int _from, int _to, int _cap, int _flow) {
			from = _from;
			to = _to;
			cap = _cap;
			flow = _flow;
		}
	};

	int n;
	vector<int> g[N];
	int fir[N], d[N];
	vector< edge > e;
	int F = 0;

	void add_edge(int u, int v, int c) {
		g[u].push_back((int)e.size());
		e.push_back(edge(u, v, c, 0LL));
		g[v].push_back((int)e.size());
		e.push_back(edge(v, u, 0LL, 0LL));
	}

	bool bfs(int s, int t) {
		for (int i = 1; i <= n; ++i) d[i] = INF;
		d[s] = 0;
		vector<int> q;
		q.push_back(s);
		for (int i = 0; i < (int)q.size(); ++i) {
			int v = q[i];
			for (int num : g[v]) {
				int to = e[num].to;
				if (e[num].rem() && d[v] + 1 < d[to]) {
					d[to] = d[v] + 1;
					q.push_back(to);
				}
			}
		}
		return d[t] != INF;
	}

	int dfs(int v, int t, int c = INF) {
		if (v == t) {
			F += c;
			return c;
		}
		for (; fir[v] < (int)g[v].size(); ++fir[v]) {
			int i = g[v][fir[v]];
			int to = e[i].to;
			if (d[v] + 1 == d[to] && e[i].rem()) {
				int x = dfs(to, t, min(c, e[i].rem()));
				if (x) {
					e[i].flow += x;
					e[i ^ 1].flow -= x;
					return x;
				}
			}
		}
		return 0;
	}

	int max_flow(int s, int t) {
		F = 0;
		while (bfs(s, t)) {
			for (int i = 1; i <= n; ++i) fir[i] = 0;
			while (dfs(s, t)) ;
		}
		return F;
	}
};

const int N = 105;

struct SHIP
{
	int x, a, f, p;
	SHIP() {}
	SHIP(int _x, int _a, int _f, int _p) {
		x = _x, a = _a, f = _f, p = _p;
	}
};

SHIP ship[N * 1000];

int d[N][N];
int value[N * 1000];
vector< pair<int, int> > list[N * 1000];

ghost main() {
	ios_base::sync_with_stdio(false);
	cin.tie(0);
	int n, m;
	cin >> n >> m;
	for (int i = 1; i <= n; ++i) {
		for (int j = 1; j <= n; ++j) {
			d[i][j] = INF;
		}
		d[i][i] = 0;
	}
	for (int i = 0; i < m; ++i) {
		int u, v;
		cin >> u >> v;
		d[u][v] = d[v][u] = 1;
	}
	for (int k = 1; k <= n; ++k) {
		for (int i = 1; i <= n; ++i) {
			for (int j = 1; j <= n; ++j) {
				if (d[i][k] != INF && d[k][j] != INF) {
					uin(d[i][j], d[i][k] + d[k][j]);
				}
			}
		}
	}
	int s, b, k;
	cin >> s >> b >> k;
	for (int i = 1; i <= s; ++i) {
		cin >> ship[i].x >> ship[i].a >> ship[i].f >> ship[i].p;
	}
	for (int i = 1; i <= b; ++i) {
		int x, d, g;
		cin >> x >> d >> g;
		list[x].push_back(make_pair(d, g));
	}
	for (int i = 1; i <= n; ++i) {
		sort(list[i].begin(), list[i].end());
		for (int j = 1; j < (int)list[i].size(); ++j) {
			uax(list[i][j].second, list[i][j - 1].second);
		}
	}
	for (int i = 1; i <= s; ++i) {
		bool ok = 0;
		for (int v = 1; v <= n; ++v) {
			if (d[ship[i].x][v] > ship[i].f || list[v].empty()) continue;
			int l = 0, r = (int)list[v].size();
			while (r - l > 1) {
				int mid = (l + r) >> 1;
				if (list[v][mid].first <= ship[i].a) {
					l = mid;
				} else {
					r = mid;
				}
			}
			if (list[v][l].first <= ship[i].a) {
				uax(value[i], list[v][l].second);
				ok = 1;
			}
		}
		if (!ok) value[i] = -INF;
	}
	for (int i = 1; i <= s; ++i) {
		if (value[i] != -INF) value[i] -= ship[i].p;
	}
	Dinic::n = s + 2;
	for (int i = 0; i < k; ++i) {
		int u, v;
		cin >> u >> v;
		Dinic::add_edge(u, v, INF);
	}
	int S = s + 1, T = s + 2;
	int sumpos = 0;
	for (int i = 1; i <= s; ++i) {
		if (value[i] > 0) {
			Dinic::add_edge(S, i, value[i]);
			sumpos += value[i];
		} else {
			Dinic::add_edge(i, T, -value[i]);
		}
	}
	int res = sumpos - Dinic::max_flow(S, T);
	cout << res << '\n';
	return 0;
} // kek ;

#include <bits/stdc++.h>
using namespace std;

typedef long long i64;

struct Dinic {
	struct Edge {
		i64 flow;
		int to, next;
	};
	vector<Edge> edges;
	vector<int> adia, at, dist;
	int S, D;
	void add_Edge(int from, int to, i64 cap) {
		edges.push_back( { cap, to, adia[from] });
		adia[from] = edges.size() - 1;
		edges.push_back( { 0, from, adia[to] });
		adia[to] = edges.size() - 1;
	}
	bool bfs() {
		queue<int> q;
		fill(dist.begin(), dist.end(), 1e9);
		dist[S] = 0;
		q.push(S);
		while (!q.empty()) {
			int x = q.front();
			q.pop();
			for (int i = adia[x]; i != -1; i = edges[i].next) {
				if (dist[edges[i].to] > dist[x] + 1 && edges[i].flow) {
					dist[edges[i].to] = 1 + dist[x];
					q.push(edges[i].to);
				}
			}
		}
		return dist[D] < 1e9;
	}
	i64 dfs(int nod, i64 fmax) {
		if (nod == D)
			return fmax;
		while (at[nod] != -1) {
			Edge &e = edges[at[nod]];
			i64 f;
			if (dist[e.to] == dist[nod] + 1 && e.flow
					&& (f = dfs(e.to, min(fmax, e.flow)))) {
				e.flow -= f;
				edges[at[nod] ^ 1].flow += f;
				return f;
			}
			at[nod] = edges[at[nod]].next;
		}
		return 0;
	}
	i64 GetFlow() {
		i64 f = 0;
		while (bfs()) {
			at = adia;
			while (i64 x = dfs(S, 1e18))
				f += x;
		}
		return f;
	}
	Dinic(int n = 0, int s = 0, int d = 0) {
		S = s, D = d;
		at = dist = adia = vector<int>(n + 1, -1);
	}
};

const int NMAX = 110;
int dmin[NMAX][NMAX];
struct Object { int cost, nod, power, id, fuel, atac; };
vector <Object> ships, bases;
vector <pair <int, int>> dependencies;
int n;
int best_cost[NMAX]; /// cel mai bun cost momentan pt o baza din nod

void get_cost_nave()
{
	fill(best_cost, best_cost + n + 1, -1);

	vector <int> nv(ships.size());
	iota(nv.begin(), nv.end(), 0);

	sort(nv.begin(), nv.end(), [](int a, int b) {
			return ships[a].power < ships[b].power;
	});
	sort(bases.begin(), bases.end(), [](Object a, Object b) {
			return a.power < b.power;
	});

	int it = 0;
	for (auto i : nv) {
		while (it != bases.size() && ships[i].power >= bases[it].power) {
			best_cost[bases[it].nod] = max(best_cost[bases[it].nod], bases[it].cost);
			it++;
		}
		int best = -1;
		for (int nod = 1; nod <= n; nod++)
			if (dmin[nod][ships[i].nod] <= ships[i].fuel)
				best = max(best, best_cost[nod]);
		ships[i].atac = best;
	}
}

void read()
{
	int m, a, b;
	scanf("%d%d", &n, &m);
	fill(dmin[0], dmin[n + 1], 1e9);
	for (int i = 1; i <= n; i++)
		dmin[i][i] = 0;

	while (m--) {
		scanf("%d%d", &a, &b);
		dmin[a][b] = dmin[b][a] = 1;
	}

	for (int k = 1; k <= n; k++)
		for (int i = 1; i <= n; i++)
			for (int j = 1; j <= n; j++)
				dmin[i][j] = min(dmin[i][j], dmin[i][k] + dmin[k][j]);

	int s, k;
	scanf("%d%d%d", &s, &b, &k);
	ships.resize(s);
	bases.resize(b);
	dependencies.resize(k);

	for (auto & i : ships) {
		scanf("%d%d%d%d", &i.nod, &i.power, &i.fuel, &i.cost);
		i.fuel = min(i.fuel, 1000000);
	}
	for (auto & i : bases)
		scanf("%d%d%d", &i.nod, &i.power, &i.cost);
	for (auto & i : dependencies)
		scanf("%d%d", &i.first, &i.second);
}

int main()
{
	read();
	get_cost_nave();

	i64 ans = 0;
	int cnt = 2, S = 1, D = 2;
	const i64 inf = 1e18;

	for (auto & i : dependencies) {
		i.first--, i.second--;
		if (!ships[i.first].id)
			ships[i.first].id = ++cnt;
		if (!ships[i.second].id)
			ships[i.second].id = ++cnt;
	}
	Dinic flow(cnt + 1, S, D);

	for (auto i : ships) {
		if (i.id) {
			if (i.atac == -1)
				flow.add_Edge(i.id, D, inf);
			else {
				int castig = i.atac - i.cost;
				if (castig > 0) {
					ans += castig;
					flow.add_Edge(S, i.id, castig);
				}
				else
					flow.add_Edge(i.id, D, -castig);
			}
		}
		else
			ans += max(0, i.atac - i.cost);
	}

	for (auto i : dependencies)
		flow.add_Edge(ships[i.first].id, ships[i.second].id, inf);

	ans -= flow.GetFlow();

	cout << ans << '\n';

	return 0;
}

#include <cstdio>
#include <cstring>

#include <algorithm>
#include <queue>
#include <vector>
#include <tuple>

#define LOG(FMT...) fprintf(stderr, FMT)

using namespace std;

typedef long long ll;

template <class T>
class is_zero {
public:
    bool operator()(const T& x) const;
};

template <>
class is_zero<long long> {
public:
    bool operator()(const ll& x) const { return x == 0; }
};

template <class WeightT = int, class ZeroPredicator = is_zero<WeightT> >
class flow_graph {
public:
    typedef WeightT weight_type;
    typedef const weight_type& const_weight_reference;
    typedef weight_type* weight_array_type;

private:
    struct edge {
        int v;
        weight_type w;
        edge *next, *rev;
    };

    int v, e;
    edge *pool, *used;
    edge** adj;
    ZeroPredicator zero_predicator;

    edge* add_edge(int u, int v, const_weight_reference w) {
        edge* p = used;
        ++used;
        p->v = v;
        p->w = w;
        p->next = adj[u];
        adj[u] = p;
        return p;
    }

    bool bfs(int s, int t, int* level) {
        memset(level, -1, sizeof(int) * v);
        std::queue<int> q;
        q.push(s);
        level[s] = 0;
        while (!q.empty()) {
            int u = q.front();
            q.pop();
            for (edge* p = adj[u]; p; p = p->next)
                if (!zero_predicator(p->w) && level[p->v] == -1) {
                    level[p->v] = level[u] + 1;
                    if (p->v == t)
                        return true;
                    q.push(p->v);
                }
        }
        return false;
    }

    weight_type dfs(int u, int t, weight_type lim, edge** cadj, int* level) {
        if (u == t)
            return lim;
        weight_type flow = 0;
        for (edge*& p = cadj[u]; p; p = p->next)
            if (!zero_predicator(p->w) && level[u] < level[p->v]) {
                weight_type f = dfs(p->v, t, std::min(p->w, lim), cadj, level);
                flow += f;
                lim -= f;
                p->w -= f;
                p->rev->w += f;
                if (zero_predicator(lim))
                    return flow;
            }
        return flow;
    }

    weight_type dfs(int u, int t, edge** cadj, int* level) {
        weight_type flow = 0;
        for (edge*& p = cadj[u]; p; p = p->next)
            if (!zero_predicator(p->w) && level[u] < level[p->v]) {
                weight_type f = dfs(p->v, t, p->w, cadj, level);
                flow += f;
                p->w -= f;
                p->rev->w += f;
            }
        return flow;
    }

public:
    flow_graph() {}

    flow_graph(int v, int e, ZeroPredicator zero_predicator = is_zero<WeightT>())
        : v(v), e(e), zero_predicator(zero_predicator) {
        pool = new edge[e * 2];
        adj = new edge*[v];
        memset(pool, 0, sizeof(edge) * e * 2);
        memset(adj, 0, sizeof(edge*) * v);
        used = pool;
    }

    ~flow_graph() {
        delete[] pool;
        delete[] adj;
    }

    void link(int u, int v, const_weight_reference w) {
        edge *p = add_edge(u, v, w), *q = add_edge(v, u, 0);
        p->rev = q;
        q->rev = p;
    }

    /**
     * Calculate the maximum flow from `s` to `t`. Using the dinic algorithm.
     * time complexity: O(n^2e)
     **/
    weight_type max_flow(int s, int t) {
        int* level = new int[v];
        edge** cadj = new edge*[v];
        weight_type flow = 0;
        while (bfs(s, t, level)) {
            memcpy(cadj, adj, sizeof(edge*) * v);
            flow += dfs(s, t, cadj, level);
        }
        delete[] level;
        delete[] cadj;
        return flow;
    }
};

const int N = 110, S = 100010, K = 1010, INF = 1e9 + 10;
const ll LINF = 1LL << 53;

int n, m, s, b, k;

int dist[N][N];
int sx[S], a[S], f[S], p[S], bx[S], d[S], g[S];
vector<pair<int, int> > best[N];
pair<int, int> ed[K];
ll good[S];
int rel[S];

int main() {
  scanf("%d%d", &n, &m);
  for (int i = 1; i <= n; ++i)
    for (int j = 1; j <= n; ++j)
      dist[i][j] = i == j ? 0 : INF;
  while (m--) {
    int u, v;
    scanf("%d%d", &u, &v);
    if (u != v)
      dist[u][v] = dist[v][u] = 1;
  }
  for (int i = 1; i <= n; ++i)
    for (int j = 1; j <= n; ++j)
      for (int k = 1; k <= n; ++k)
        dist[j][k] = min(dist[j][k], dist[j][i] + dist[i][k]);
  scanf("%d%d%d", &s, &b, &k);
  for (int i = 1; i <= s; ++i)
    scanf("%d%d%d%d", &sx[i], &a[i], &f[i], &p[i]);
  for (int i = 1; i <= b; ++i) {
    scanf("%d%d%d", &bx[i], &d[i], &g[i]);
    best[bx[i]].emplace_back(d[i], g[i]);
  }
  for (int i = 1; i <= n; ++i) {
    sort(best[i].begin(), best[i].end());
    for (int j = 1; j < best[i].size(); ++j)
      best[i][j].second = max(best[i][j - 1].second, best[i][j].second);
  }
  memset(good, -1, sizeof(good));
  for (int i = 1; i <= s; ++i)
    for (int j = 1; j <= n; ++j)
      if (f[i] >= dist[sx[i]][j]) {
        auto it = lower_bound(best[j].begin(), best[j].end(), make_pair(a[i] + 1, 0));
        if (it != best[j].begin())
          good[i] = max(good[i], ll((it - 1)->second));
      }
  int cnt = 0;
  int S = ++cnt, T = ++cnt;
  for (int i = 1; i <= k; ++i) {
    int u, v;
    scanf("%d%d", &u, &v);
    ed[i] = make_pair(u, v);
    if (!rel[u])
      rel[u] = ++cnt;
    if (!rel[v])
      rel[v] = ++cnt;
  }
  flow_graph<long long> g(cnt + 1, k + (cnt - 2));
  ll ans = 0;
  for (int i = 1; i <= k; ++i) {
    int u, v;
    tie(u, v) = ed[i];
    g.link(rel[u], rel[v], LINF);
  }
  for (int i = 1; i <= s; ++i) {
    if (good[i] == -1) good[i] = -LINF;
    else good[i] -= p[i];
    if (rel[i]) {
      if (good[i] >= 0) {
        ans += good[i];
        g.link(S, rel[i], good[i]);
      } else {
        g.link(rel[i], T, -good[i]);
      }
    } else {
      ans += max(0LL, good[i]);
    }
  }
  ans -= g.max_flow(S, T);
  printf("%lld\n", ans);
  return 0;
}

//#pragma GCC optimize ("Ofast")
//#pragma GCC target ("avx,avx2,fma")

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;

typedef pair<int,int> pii;
typedef pair<ll,ll> pll;

#define F first
#define S second
#define pb push_back
#define eb emplace_back
#define mk make_pair
#define all(x) x.begin(), x.end()

#define REP(i,n) for(int i = 0; i < int(n); i++)
#define FOR(i,a,b) for(int i = a; i <= int(b); i++)

const int N = 105;
const int INF = 1e9+5;
const ll INF_LL = 1e15+5;

int g[N][N], dist[N][N];

struct Ship {
	int loc, attack, fuel, price;

	void read() {
		cin >> loc >> attack >> fuel >> price;
		--loc;
	}
};

vector<pii> reward[N];

struct Base {
	int loc, defence, gold;

	void read() {
		cin >> loc >> defence >> gold;
		--loc;
		reward[loc].emplace_back(defence, gold);
	}

};

template<typename T>
void max_self(T& a, T b) {
	a = max(a, b);
}

// Dinic's algoritm for maximum flow O(E*V^2)
// tested on: https://www.spoj.com/problems/FASTFLOW/

template<typename flow_t>
class Dinic {
public:

    Dinic(int _n, int _source, int _sink) : n(_n), source(_source), sink(_sink) {
        g.resize(n);
        flow.resize(n, vector<flow_t>(n));
        level.resize(n);
        ptr.resize(n);
    }

    void add_edge(int from, int to, flow_t cap) {
        g[from].push_back(to);
        g[to].push_back(from);
        flow[from][to] += cap;
    }

    bool bfs() {
        vector<int> q{source};
        for(int i = 0; i < (int) q.size(); i++) {
            int u = q[i];
            for(int v : g[u]) {
                if(level[v] == -1 && flow[u][v] > 0) {
                    level[v] = level[u] + 1;
                    q.push_back(v);
                }
            }
        }

        return level[sink] != -1;
    }

    flow_t dfs(int u, flow_t pushed) {
        if(pushed == 0) {
            return 0;
        }
        if(u == sink) {
            return pushed;
        }
        for(int& pos = ptr[u]; pos < (int) g[u].size(); pos++) {
            int v = g[u][pos];
            if(level[v] != level[u] + 1 || flow[u][v] == 0) {
                continue;
            }
            flow_t maybe_push = dfs(v, min(pushed, flow[u][v]));
            if(maybe_push == 0) {
                continue;
            }
            flow[u][v] -= maybe_push;
            flow[v][u] += maybe_push;
            return maybe_push;
        }
        return 0;
    }

    flow_t max_flow() {
        flow_t mf(0);
        while(true) {
            level.assign(n, -1);
            level[source] = 0;
            if(!bfs()) {
                break;
            }
            ptr.assign(n, 0);
            flow_t now;
            do {
                now = dfs(source, FLOW_MAX);
                mf += now;
            } while(now != 0);
        }

        return mf;
    }
private:
    const flow_t FLOW_MAX = numeric_limits<flow_t>::max() / 2;
    vector<vector<int>> g;
    vector<vector<flow_t>> flow;
    vector<int> level, ptr;
    int n, source, sink;
};

int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);

	fill((int *) dist, (int *) dist + N * N, INF);
	REP(i, N) dist[i][i] = 0;

	int n, m;
	cin >> n >> m;

	REP(i, m) {
		int a, b;
		cin >> a >> b;
		--a, --b;
		g[a][b] = g[b][a] = 1;
		dist[a][b] = dist[b][a] = 1;
	}

	REP(k, n)REP(i, n)REP(j, n) {
		dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
	}

	int S, B, K;
	cin >> S >> B >> K;
	vector<Ship> ships(S);
	vector<Base> bases(B);

	for(auto& s : ships) {
		s.read();
	}
	for(auto& b : bases) {
		b.read();
	}

	REP(i, n) {
		sort(all(reward[i]));
		int sz = reward[i].size();
		FOR(j, 1, sz-1) {
			reward[i][j].S = max(reward[i][j].S, reward[i][j-1].S);
		}
	}
	//for each ship, find the best base to attack

	vector<long long> ship_reward(S, -INF_LL);
	REP(i, S) {
		Ship s = ships[i];
		REP(base, n) if(dist[s.loc][base] < INF) {
			int lo = 0, hi = (int) reward[base].size()-1;
			int idx = -1;
			while(lo <= hi) {
				int mid = (lo + hi)/2;
				if(reward[base][mid].F <= s.attack) {
					idx = mid;
					lo = mid+1;
				}
				else {
					hi = mid-1;
				}
			}
			if(idx == -1) {
				continue;
			}
			max_self(ship_reward[i], (long long) reward[base][idx].S - s.price);
		}
	}
	//#warning TODO: read dependencies

	vector<pii> dependencies;
	REP(i, K) {
		int a, b;
		cin >> a >> b;
		--a, --b;
		dependencies.emplace_back(a, b);
	}
	long long ans = 0;
	REP(i, S) {
		if(ship_reward[i] > 0) {
			ans += ship_reward[i];
		}
	}
	map<int,int> id;
	int nodes = 0;
	for(auto [u, v] : dependencies) {
		if(!id.count(u)) {
			id[u] = nodes++;
		}
		if(!id.count(v)) {
			id[v] = nodes++;
		}
	}
	int source = nodes++;
	int sink = nodes++;

	Dinic<long long> graph(nodes, source, sink);

	for(auto [u, _] : id) {
		if(ship_reward[u] >= 0) {
			graph.add_edge(source, id[u], ship_reward[u]);
		}
		else {
			graph.add_edge(id[u], sink, -ship_reward[u]);
		}
	}
	for(auto [u, v] : dependencies) {
		graph.add_edge(id[u], id[v], INF_LL);
	}

	ans -= graph.max_flow();
	cout << ans << "\n";

}

/*
 * 	augmenting path in flow network represents a dependency that is currently NOT satisfied
 *
 *  subtract min cut in flow network -> make all dependency relationships satisfied
 *
 *  so ans = sum(ships with positive reward) - min cut in flow network
 */

#include <bits/stdc++.h>
using namespace std;

using pii = pair<int, int>;
using ll = long long;
using cap_type = ll;

constexpr ll inf = 1e12;

struct edge {
	int to, rev;
	cap_type cap;
	edge(int t, cap_type c, int r) : to(t), rev(r), cap(c) {}
};
using graph = vector<vector<edge>>;

void add_edge(graph& g, int from, int to, cap_type cap) {
	g[from].emplace_back(to, cap, g[to].size());
	g[to].emplace_back(from, 0, g[from].size() - 1);
}

cap_type augment(graph& g, vector<int> const& level, vector<int>& iter, int v, int t, cap_type f) {
	if(v == t) return f;
	for(int& i = iter[v]; i < (int)g[v].size(); ++i) {
		auto& e = g[v][i];
		if(e.cap > 0 && level[v] < level[e.to]) {
			const auto d = augment(g, level, iter, e.to, t, min(f, e.cap));
			if(d > 0) {
				e.cap -= d;
				g[e.to][e.rev].cap += d;
				return d;
			}
		}
	}
	return 0;
}

cap_type max_flow(graph& g, int s, int t) {
	cap_type flow = 0;
	while(true) {
		vector<int> level(g.size(), -1);
		level[s] = 0;
		queue<int> que;
		que.push(s);
		while(!que.empty()) {
			const int v = que.front();
			que.pop();
			for(auto const& e : g[v]) {
				if(e.cap > 0 && level[e.to] < 0) {
					level[e.to] = level[v] + 1;
					que.push(e.to);
				}
			}
		}
		if(level[t] < 0) return flow;
		vector<int> iter(g.size());
		cap_type f = 0;
		while((f = augment(g, level, iter, s, t, inf)) > 0) {
			flow += f;
		}
	}
	assert(false);
	return 0;
}

int main() {
	ios_base::sync_with_stdio(false); cin.tie(0);

	int n, m; cin >> n >> m;
	vector<vector<int>> d(n, vector<int>(n, 100000000));
	for(int i = 0; i < n; ++i) {
		d[i][i] = 0;
	}
	for(int i = 0; i < m; ++i) {
		int u, v; cin >> u >> v;
		v--, u--;
		if(u == v) continue;
		d[u][v] = d[v][u] = 1;
	}
	for(int k = 0; k < n; ++k) {
		for(int i = 0; i < n; ++i) {
			for(int j = 0; j < n; ++j) {
				d[i][j] = min(d[i][k] + d[k][j], d[i][j]);
			}
		}
	}
	ll s, b, k; cin >> s >> b >> k;
	vector<int> sx(s), a(s), f(s), p(s);
	for(int i = 0; i < s; ++i) {
		cin >> sx[i] >> a[i] >> f[i] >> p[i];
		sx[i]--;
	}
	vector<int> dx(b), def(b), gain(b);
	for(int i = 0; i < b; ++i) {
		cin >> dx[i] >> def[i] >> gain[i];
		dx[i]--;
	}

	vector<vector<map<int, int>>> cost(n, vector<map<int, int>>(n));
	for(int v = 0; v < n; ++v) {
		auto check = [] (auto const& p1, auto const& p2) {
			return p1.first >= p2.first && p1.second <= p2.second;
		};
		for(int j = 0; j < b; ++j) {
			const int u = dx[j];
			const auto tmp = make_pair(def[j], gain[j]);
			auto it = cost[v][u].lower_bound(def[j]);
			while(it != cost[v][u].end() && check(*it, tmp)) {
				it = cost[v][u].erase(it);
			}
			if(it == cost[v][u].begin() || prev(it)->second < tmp.second) {
				cost[v][u][def[j]] = gain[j];
			}
		}
	}

	graph g(s + 2);
	const int src = s, sink = s + 1;
	ll ans = 0;
	for(int i = 0; i < s; ++i) {
		const int u = sx[i];
		ll prof = -inf;
		for(int v = 0; v < n; ++v) {
			if(d[u][v] > f[i] || cost[u][v].empty()) continue;
			auto it = cost[u][v].upper_bound(a[i]);
			if(it == begin(cost[u][v])) continue;
			it = prev(it);
			prof = max(prof, (ll)it->second - p[i]);
		}

		if(prof == -inf) {
			add_edge(g, i, sink, inf);
		} else {
			if(prof < 0) {
				add_edge(g, src, i, 0);
				add_edge(g, i, sink, -prof);
			} else {
				add_edge(g, src, i, prof);
				add_edge(g, i, sink, 0);
				ans += prof;
			}
		}
	}

	for(int i = 0; i < k; ++i) {
		int s1, s2; cin >> s1 >> s2;
		s1--, s2--;
		if(s1 == s2) continue;
		add_edge(g, s1, s2, inf);
	}

	cout << ans - max_flow(g, src, sink) << endl;
}

#include <bits/stdc++.h>
using namespace std;
#define pb push_back

typedef long long ll;

#define N 105
#define M 100005
template <class T> void chkmax(T &a, T b) {if (a < b) a = b;}
//template <class T> void chkmin(T &a, T b) {if (a > b) a = b;}

vector <int> v[N];
vector <int> vs[N], vb[N];

int n, m;
int nn, mm, kk;

int f[M], d[M], g[M], a[M], x[M], y[M], p[M];

bool cmpf(int x, int y) {
	return f[x] < f[y];
}

int dd[N];

int fen[M<<1];

int val[M<<1], vals;
void update(int k, int v) {
    for ( ; k <= vals; k += k & -k) {
        chkmax(fen[k], v);
    }
    return;
}
const int inf = 0x3f3f3f3f;
int calc_mx(int k) {
	int res = -inf;
    for ( ; k; k -= k & -k) {
        chkmax(res, fen[k]);
    }
    return res;
}

void update(int k) {
    for (auto x : vb[k]) {
        update(d[x], g[x]);
    }
}

int rd[M];
void solve(int k) {
    memset(dd, -1, sizeof dd);
    memset(fen, -1, sizeof fen);
    vector <int> A, B;
    A.pb(k); int now = 0;
    update(k); int tot = 1;
    int t = 0;
    while (t < vs[k].size() && f[vs[k][t]] == 0) {
        int kk = vs[k][t];
        chkmax(rd[kk], calc_mx(a[kk]));
        t ++;
    }
    while (!A.empty() && t < vs[k].size()) {
		B.clear();
		now ++;
        for (auto x : A) {
            for (auto y : v[x]) {
                if (dd[y] < 0) {
					B.pb(y);
                    update(y);
                    dd[y] = dd[x] + 1;
                }
            }
        }
        tot += B.size();
        while (t < vs[k].size() && f[vs[k][t]] == now) {
            int kk = vs[k][t];
            chkmax(rd[kk], calc_mx(a[kk]));
            t ++;
        }
        A.swap(B);
    }
    while (t < vs[k].size()) {
        int kk = vs[k][t];
        chkmax(rd[kk], calc_mx(a[kk]));
        t ++;
    }
    return;
}

vector <int> vv[M];

bool vd[M], vis[M];

void dfs(int k) {
    vd[k] = 1; vis[k] = 1;
    for (auto x : vv[k]) {
        if (vd[x]) continue;
        dfs(x);
    }
    return;
}

map <int, int> H;

int tot;

const ll linf = 1e16;

struct Dinic {
	struct edge {
		int u, v;
		ll cap, flow;
		edge() {}
		edge(int u, int v, ll cap): u(u), v(v), cap(cap), flow(0) {}
	};
	int n;
	vector <edge> E;
	vector < vector <int> > g;
	vector <int> d, pt;

	Dinic(int n): n(n), E(0), g(n), d(n), pt(n) {}
	Dinic() {}
	void init(int _n) {
		n = _n;
		g.resize(n); d.resize(n);
		E.resize(0); pt.resize(n);
		for (int i = 0; i < n; i ++) g[i].clear();
	}
	void add_edge(int u, int v, ll cap) {
		if (u != v) {
			E.push_back(edge(u, v, cap));
			g[u].push_back(E.size() - 1);
			E.push_back(edge(v, u, 0));
			g[v].push_back(E.size() - 1);
		}
	}

	bool BFS(int S, int T) {
		queue<int> q;
		q.push(S);
		fill(d.begin(), d.end(), n + 1);
		d[S] = 0;
		while(!q.empty()) {
			int u = q.front(); q.pop();
			if (u == T) break;
			for (int i = 0; i < g[u].size(); i ++) {
				int k = g[u][i];
				edge &e = E[k];
				if (e.flow < e.cap && d[e.v] > d[e.u] + 1) {
					d[e.v] = d[e.u] + 1;
					q.push(e.v);
				}
			}
		}
		return d[T] != n + 1;
	}

	ll DFS(int u, int T, ll flow = -1) {
		if (u == T || flow == 0) return flow;
		for (int &i = pt[u]; i < g[u].size(); ++i) {
			edge &e = E[g[u][i]];
			edge &oe = E[g[u][i]^1];
			if (d[e.v] == d[e.u] + 1) {
				ll amt = e.cap - e.flow;
				if (flow != -1 && amt > flow) amt = flow;
				if (ll pushed = DFS(e.v, T, amt)) {
					e.flow += pushed;
					oe.flow -= pushed;
					return pushed;
				}
			}
		}
		return 0;
	}

	ll maxflow(int S, int T) {
		ll res = 0;
		while (BFS(S, T)) {
			fill(pt.begin(), pt.end(), 0);
			while (ll flow = DFS(S, T)) res += flow;
		}
		return res;
	}
} A;

ll tot_sum;

bool vvis[M];

void add_edge(int x, int y) {
	vvis[x] = vvis[y] = 1;
    if (!H.count(x)) {
        H[x] = ++ tot;
        int t = rd[x] - p[x];
        if (t < 0) A.add_edge(tot, 1, -t);
        else A.add_edge(0, tot, t), tot_sum += t;
    }
    if (!H.count(y)) {
        H[y] = ++ tot;
        int t = rd[y] - p[y];
        if (t < 0) A.add_edge(tot, 1, -t);
        else A.add_edge(0, tot, t), tot_sum += t;
    }
    A.add_edge(H[x], H[y], linf);
}

int main() {
    memset(rd, -1, sizeof rd);
	scanf("%d %d", &n, &m);
    for (int i = 1; i <= m; i ++) {
		int x, y;
		scanf("%d %d", &x, &y);
		v[x].pb(y);
		v[y].pb(x);
    }
    scanf("%d %d %d", &nn, &mm, &kk);
    for (int i = 1; i <= nn; i ++) {
        scanf("%d %d %d %d", &x[i], &a[i], &f[i], &p[i]);
        if (f[i] >= n) f[i] = n-1;
        val[vals++] = a[i];
        vs[x[i]].pb(i);
    }
    for (int i = 1; i <= mm; i ++) {
        scanf("%d %d %d", &y[i], &d[i], &g[i]);
        vb[y[i]].pb(i);
        val[vals++] = d[i];
    }
    sort(val, val+vals);
    vals = unique(val, val+vals) - val;
    for (int i = 1; i <= nn; i ++) {
        a[i] = lower_bound(val, val+vals, a[i]) - val + 1;
    }
    for (int i = 1; i <= mm; i ++) {
        d[i] = lower_bound(val, val+vals, d[i]) - val + 1;
    }
    for (int i = 1; i <= n; i ++) sort(vs[i].begin(), vs[i].end(), cmpf);
    for (int i = 1; i <= n; i ++) if (!vs[i].empty()) solve(i);
    for (int i = 1; i <= nn; i ++) if (rd[i] < 0) vis[i] = 1;
    while (kk --) {
        int x, y;
		scanf("%d %d", &x, &y);
        vv[y].pb(x);
    }
    for (int i = 1; i <= nn; i ++) if (vis[i] && !vd[i]) dfs(i);
    A.init(3000);
    tot = 1;
    for (int i = 1; i <= nn; i ++) if (!vis[i]) {
        for (auto x : vv[i]) if (!vis[x]) {
            add_edge(x, i);
        }
    }
    ll flow = A.maxflow(0, 1);
    flow = tot_sum - flow;
    for (int i = 1; i <= nn; i ++) if (!vvis[i] && !vis[i] && rd[i] - p[i] > 0) flow += rd[i] - p[i];
    printf("%I64d\n", flow);
    return 0;
}

#include <iostream>
#include <vector>
#include <algorithm>
#include <tuple>
#include <queue>
using namespace std;
typedef long long ll;
typedef tuple<int, int, int> event;

const int MAXN = 100100;
const ll INFTY = 1LL<<60;
int N, M, S, B, K;
ll dist[105][105];
ll maxG[105];
int spos[MAXN], fuel[MAXN], price[MAXN];
int bpos[MAXN], gold[MAXN];
ll profit[MAXN];
vector<event> E;

struct Edge
{
    int u, v;
    ll cap, flow;
    Edge() {}
    Edge(int u, int v, ll cap): u(u), v(v), cap(cap), flow(0) {}
};

struct Dinic
{
    const static ll INFTY = 1LL<<60;
    int N;
    vector<Edge> E;
    vector<vector<int> > g;
    vector<int> d, pt;

    Dinic(int N): N(N), E(0), g(N), d(N), pt(N) {}

    void addEdge(int u, int v, ll cap)
    {
        if (u != v)
        {
            E.push_back(Edge(u, v, cap));
            g[u].push_back(E.size() - 1);
            E.push_back(Edge(v, u, 0));
            g[v].push_back(E.size() - 1);
        }
    }

    bool BFS(int S, int T)
    {
        queue<int> q;
        q.push(S);
        fill(d.begin(), d.end(), N + 1);
        d[S] = 0;

        while (!q.empty())
        {
            int u = q.front();
            q.pop();
            if (u == T)
                break;
            for (int k : g[u])
            {
                Edge &e = E[k];
                if (e.flow < e.cap && d[e.v] > d[e.u] + 1)
                {
                    d[e.v] = d[e.u] + 1;
                    q.push(e.v);
                }
            }
        }

        return d[T] != N + 1;
    }

    ll DFS(int u, int T, ll flow = INFTY)
    {
        if (u == T || flow == 0)
            return flow;

        for (int &i = pt[u]; i < g[u].size(); ++i)
        {
            Edge &e = E[g[u][i]];
            Edge &oe = E[g[u][i]^1];
            if (d[e.v] == d[e.u] + 1)
            {
                ll amt = min(flow, e.cap - e.flow);
                if (ll pushed = DFS(e.v, T, amt))
                {
                    e.flow += pushed;
                    oe.flow -= pushed;
                    return pushed;
                }
            }
        }

        return 0;
    }

    ll maxFlow(int S, int T)
    {
        ll total = 0;
        while (BFS(S, T))
        {
            fill(pt.begin(), pt.end(), 0);
            while (ll flow = DFS(S, T))
                total += flow;
        }
        return total;
    }
};

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);

    cin >> N >> M;
    for (int i = 1; i <= N; i++)
        for (int j = i + 1; j <= N; j++)
            dist[i][j] = dist[j][i] = INFTY;
    for (int i = 0, a, b; i < M; i++)
    {
        cin >> a >> b;
        if (a != b)
            dist[a][b] = dist[b][a] = 1;
    }
    for (int k = 1; k <= N; k++)
        for (int i = 1; i <= N; i++)
            for (int j = 1; j <= N; j++)
                dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);

    cin >> S >> B >> K;
    for (int i = 1, a; i <= S; i++)
    {
        cin >> spos[i] >> a >> fuel[i] >> price[i];
        E.emplace_back(a, 1, i);
    }
    for (int i = 1, d; i <= B; i++)
    {
        cin >> bpos[i] >> d >> gold[i];
        E.emplace_back(d, 0, i);
    }

    for (int i = 1; i <= S; i++)
        profit[i] = -INFTY;
    for (int i = 1; i <= N; i++)
        maxG[i] = -INFTY;
    sort(E.begin(), E.end());
    for (event e : E)
    {
        int power, type, idx;
        tie(power, type, idx) = e;
        if (type == 0) //base
            maxG[bpos[idx]] = max(maxG[bpos[idx]], (ll)gold[idx]);
        else //ship
        {
            for (int i = 1; i <= N; i++)
                if (fuel[idx] >= dist[spos[idx]][i])
                    profit[idx] = max(profit[idx], maxG[i] - price[idx]);
        }
    }

    Dinic dinic(S + 2);
    ll ans = 0;
    for (int i = 1; i <= S; i++)
    {
        if (profit[i] > 0)
        {
            dinic.addEdge(0, i, profit[i]);
            ans += profit[i];
        }
        else
            dinic.addEdge(i, S + 1, -profit[i]);
    }
    for (int i = 0, a, b; i < K; i++)
    {
        cin >> a >> b;
        dinic.addEdge(a, b, INFTY);
    }
    cout << ans - dinic.maxFlow(0, S + 1) << "\n";

    return 0;
}

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

int dist[100][100];

const int nax = 1e5+10;
vector<pair<int,int>> base[nax];
struct Ship {
  int x, a, f;
  ll p;
};

Ship ship[nax];
int easiest_base[100];

struct Edge {
  int end;
  ll cap;
};
vector<Edge> edges;
vector<int> node[nax];
void addEdge(int a, int b, ll w) {
  node[a].push_back(edges.size());
  edges.push_back({b,w});
  node[b].push_back(edges.size());
  edges.push_back({a,0});
}

int done[nax];
ll maxFlow(int p, int sink, ll ma = 1e18) {
  if (p == sink) return ma;
  if (ma == 0 || done[p]++) return 0;
  for (int ei : node[p]) {
    Edge&e = edges[ei];
    ll flow;
    if (e.cap && (flow=maxFlow(e.end, sink, min(ma,e.cap)))) {
      edges[ei].cap -= flow;
      edges[ei^1].cap += flow;
      return flow;
    }
  }
  return 0;
}

int has_edge[nax];

int main() {
  ios::sync_with_stdio(0); cin.tie(0);
  int n, m;
  cin >> n >> m;
  for (int i = 0; i < n; i++)
    for (int j = 0; j < n; j++)
      dist[i][j] = i==j ? 0 : 1e9;
  while (m--) {
    int a, b;
    cin >> a >> b;
    a--, b--;
    dist[a][b] = dist[b][a] = 1;
  }
  for (int k = 0; k < n; k++)
    for (int i = 0; i < n; i++)
      for (int j = 0; j < n; j++)
	dist[i][j] = min(dist[i][j], dist[i][k]+dist[k][j]);
  int ships, bases, deps;
  cin >> ships >> bases >> deps;
  for (int i = 0; i < ships; i++) {
    cin >> ship[i].x >> ship[i].a >> ship[i].f >> ship[i].p;
    ship[i].x--;
  }
  fill_n(easiest_base, n, 1e9+10);
  for (int i = 0; i < bases; i++) {
    int x, d, g;
    cin >> x >> d >> g;
    x--;
    base[x].push_back({d,g});
    easiest_base[x] = min(easiest_base[x], d);
  }
  for (int i = 0; i < n; i++) {
    sort(base[i].begin(), base[i].end());
    vector<pair<int,int>> comp = {{0,0}};
    for (auto p : base[i]) {
      if (p.second <= comp.back().second) continue;
      if (p.first == comp.back().first)
	comp.pop_back();
      comp.push_back(p);
    }
    base[i] = comp;
  }

  int source = ships, sink = ships+1, N = ships+2;
  ll sum = 0;

  for (int i = 0; i < deps; i++) {
    int a, b;
    cin >> a >> b;
    a--, b--;
    addEdge(a, b, 1e18);
    has_edge[a] = has_edge[b] = 1;
  }

  for (int i = 0; i < ships; i++) {
    int most_gold = -1;
    for (int j = 0; j < n; j++) {
      if (easiest_base[j] > ship[i].a || dist[ship[i].x][j] > ship[i].f) continue;
      int gold = prev(upper_bound(base[j].begin(), base[j].end(), make_pair(ship[i].a,(int)2e9)))->second;
      most_gold = max(most_gold, gold);
    }
    if (!has_edge[i]) {
      sum += max(most_gold-ship[i].p, 0ll);
      continue;
    }

    if (most_gold == -1)
      ship[i].p = 1e15;
    else {
      addEdge(source, i, most_gold);
      sum += most_gold;
    }
    addEdge(i, sink, ship[i].p);
    //cout << i << ' ' << ship[i].p << ' ' << max(most_gold,0) << endl;
  }

  ll flow = 0;
  while (1) {
    fill_n(done, N, 0);
    ll newflow = maxFlow(source, sink);
    if (!newflow) break;
    flow += newflow;
  }
  //cout << sum << ' ' << flow << endl;
  cout << sum-flow << endl;
}

#include <iostream>
#include <algorithm>
#include <vector>
#include <map>

#define X first
#define Y second

using namespace std;

const int maxn = 2020;
const int inf = 1e9 + 7;

struct edge {
	int a, b, cap, flow;
	edge(int a, int b, int cap) : a(a), b(b), cap(cap), flow(0) {}
};

int S = 0, T, dist[maxn], q[maxn], ptr[maxn];
vector<edge> e;
vector<int> g[maxn];

void add_edge(int a, int b, int cap) {
	g[a].push_back((int)e.size());
	e.push_back(edge(a, b, cap));
	g[b].push_back((int)e.size());
	e.push_back(edge(b, a, 0));
}

bool bfs() {
	fill(dist, dist + maxn, -1);
	dist[S] = 0;
	int qh = 0, qt = 0;
	q[qt++] = S;
	while(qh < qt and dist[T] == -1) {
		int v = q[qh++];
		for(int id : g[v]) {
			if(dist[e[id].b] == -1 and e[id].flow < e[id].cap) {
				q[qt++] = e[id].b;
				dist[e[id].b] = dist[v] + 1;
			}
		}
	}
	return dist[T] != -1;
}

int dfs(int v, int flow) {
	if(flow == 0) return 0;
	if(v == T) return flow;
	for(; ptr[v] < (int)g[v].size(); ptr[v]++) {
		int id = g[v][ptr[v]];
		if(dist[e[id].b] != dist[v] + 1) continue;
		int pushed = dfs(e[id].b, min(flow, e[id].cap - e[id].flow));
		if(pushed) {
			e[id].flow += pushed;
			e[id ^ 1].flow -= pushed;
			return pushed;
		}
	}
	return 0;
}

long long dinic() {
	long long flow = 0;
	while(bfs()) {
		fill(ptr, ptr + maxn, 0);
		while(int pushed = dfs(S, inf)) flow += pushed;
	}
	return flow;
}

int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	int n, m;
	cin >> n >> m;
	int d[n + 1][n + 1];
	for(int i = 1; i <= n; i++) {
		for(int j = 1; j <= n; j++) {
			d[i][j] = d[j][i] = inf;
		}
		d[i][i] = 0;
	}
	for(int i = 0; i < m; i++) {
		int u, v;
		cin >> u >> v;
		if(u != v) {
			d[u][v] = d[v][u] = 1;
		}
	}
	for(int k = 1; k <= n; k++) {
		for(int i = 1; i <= n; i++) {
			for(int j = 1; j <= n; j++) {
				d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
			}
		}
	}
	int s, b, k;
	cin >> s >> b >> k;
	long long spos[s], attack[s], fuel[s], price[s];
	long long bpos[b], defense[b], gold[b];
	for(int i = 0; i < s; i++) {
		cin >> spos[i] >> attack[i] >> fuel[i] >> price[i];
	}
	for(int i = 0; i < b; i++) {
		cin >> bpos[i] >> defense[i] >> gold[i];
	}
	bool indep[s] = {0};
	pair<int, int> dep[k];
	for(int i = 0; i < k; i++) {
		cin >> dep[i].X >> dep[i].Y;
		indep[dep[i].X - 1] = indep[dep[i].Y - 1] = true;
	}
	vector<pair<long long, long long> > maxpref[n + 1];
	for(int i = 1; i <= n; i++) {
		maxpref[i].push_back({0, -2 * inf});
	}
	for(int i = 0; i < b; i++) {
		maxpref[bpos[i]].push_back({defense[i], gold[i]});
	}
	for(int i = 1; i <= n; i++) {
		sort(maxpref[i].begin(), maxpref[i].end());
		for(int j = 1; j < maxpref[i].size(); j++) {
			maxpref[i][j].Y = max(maxpref[i][j].Y, maxpref[i][j - 1].Y);
		}
	}
	long long maxprofit[s];
	for(int i = 0; i < s; i++) {
		long long ans = -inf * 2;
		for(int j = 1; j <= n; j++) {
			if(d[spos[i]][j] <= fuel[i]) {
				int x = upper_bound(maxpref[j].begin(), maxpref[j].end(), make_pair(attack[i], 2ll * inf)) - maxpref[j].begin();
				ans = max(ans, 1ll * maxpref[j][x - 1].Y - price[i]);
			}
		}
		maxprofit[i] = ans;
	}
	int nxt = 1;
	int newnum[s];
	for(int i = 0; i < s; i++) {
		if(indep[i]) newnum[i] = nxt++;
	}
	T = nxt;
	for(int i = 0; i < s; i++) {
		if(indep[i]) {
			if(maxprofit[i] > 0) add_edge(S, newnum[i], maxprofit[i]);
			else if(maxprofit[i] != -inf * 2) add_edge(newnum[i], T, -maxprofit[i]);
		}
	}
	for(int i = 0; i < k; i++) {
		add_edge(newnum[dep[i].X - 1], newnum[dep[i].Y - 1], 2 * inf);
	}
	for(int i = 0; i < k; i++) {
		for(int j = 0; j < k; j++) {
			if(maxprofit[dep[j].Y - 1] == -2 * inf) {
				maxprofit[dep[j].X - 1] = -2 * inf;
			}
		}
	}
	long long ans = 0;
	for(int i = 0; i < s; i++) {
		if(maxprofit[i] > 0) ans += maxprofit[i];
	}
	cout << ans - dinic() << '\n';
	return 0;
}

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    ll n, m;
    cin >> n >> m;
    vector<vector<ll>> dist((size_t) n, vector<ll>((size_t) n, (ll) 1e16));
    for (ll i = 0; i < n; i++) {
        dist[i][i] = (ll) 0;
    }
    for (ll i = 0; i < m; i++) {
        ll u, v;
        cin >> u >> v;
        u--, v--;
        dist[u][v] = dist[v][u] = 0;
    }
    for (ll k = 0; k < n; k++) {
        for (ll i = 0; i < n; i++) {
            for (ll j = 0; j < n; j++) {
                dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
            }
        }
    }
    ll s, b, k;
    cin >> s >> b >> k;
    vector<tuple<ll, ll, ll, ll>> x((size_t) s);
    for (ll i = 0; i < s; i++) {
        cin >> get<0>(x[i]) >> get<1>(x[i]) >> get<2>(x[i]) >> get<3>(x[i]);
        get<0>(x[i])--;
    }
    vector<tuple<ll, ll, ll>> y((size_t) b);
    for (ll i = 0; i < b; i++) {
        cin >> get<0>(y[i]) >> get<1>(y[i]) >> get<2>(y[i]);
        get<0>(y[i])--;
    }
    vector<map<ll, ll>> bases((size_t) n);
    for (ll i = 0; i < b; i++) {
        bases[get<0>(y[i])][get<1>(y[i])] = get<2>(y[i]);
    }
    for (ll i = 0; i < n; i++) {
        for (auto j = bases[i].begin(); j != bases[i].end();) {
            if (j == bases[i].begin() || j->second > prev(j)->second) {
                j++;
            } else {
                j = bases[i].erase(j);
            }
        }
    }
    vector<ll> damages((size_t) s, (ll) -1e16);
    for (ll i = 0; i < s; i++) {
        for (ll j = 0; j < n; j++) {
            if (get<2>(x[i]) >= dist[get<0>(x[i])][j]) {
                auto it = bases[j].upper_bound(get<1>(x[i]));
                if (it != bases[j].begin()) {
                    damages[i] = max(damages[i], prev(it)->second - get<3>(x[i]));
                }
            }
        }
    }
    vector<vector<ll>> init_adj((size_t) s), init_adj_rev((size_t) s);
    vector<vector<pair<ll, ll>>> adj((size_t) s + 2);
    vector<map<ll, ll>> flows((size_t) s + 2);
    auto add_edge = [&](ll u, ll v, ll w) {
        adj[u].emplace_back(v, w);
        adj[v].emplace_back(u, 0);
        flows[u][v] = 0;
        flows[v][u] = 0;
    };
    for (ll i = 0; i < k; i++) {
        ll u, v;
        cin >> u >> v;
        u--, v--;
        if (u != v) {
            init_adj[u].push_back(v);
            init_adj_rev[v].push_back(u);
            add_edge(u, v, (ll) 1e16);
        }
    }
    ll o = 0;
    for (ll u = 0; u < s; u++) {
        o += max(damages[u], (ll) 0);
        if (damages[u] > 0) {
            if (!init_adj[u].empty()) {
                add_edge(s, u, damages[u]);
            }
        } else {
            if (!init_adj_rev[u].empty()) {
                add_edge(u, s + 1, -damages[u]);
            }
        }
    }
    vector<bool> visited;
    vector<ll> path;
    function<ll(ll)> visit = [&](ll u) {
        if (!visited[u]) {
            visited[u] = true;
            path.push_back(u);
            if (u == s + 1) {
                return (ll) 1e16;
            } else {
                for (auto[v, w] : adj[u]) {
                    if (w - flows[u][v] > 0) {
                        ll a = visit(v);
                        if (a > 0) {
                            return min(w - flows[u][v], a);
                        }
                    }
                }
            }
            path.pop_back();
        }
        return (ll) 0;
    };
    while (true) {
        visited.assign((ll) s + 2, false);
        path.clear();
        ll a = visit(s);
        if (a > 0) {
            for (ll i = 1; i < (ll) path.size(); i++) {
                flows[path[i - 1]][path[i]] += a;
                flows[path[i]][path[i - 1]] -= a;
            }
            o -= a;
        } else {
            break;
        }
    }
    cout << o << endl;
    return 0;
}

//~ while (clock()<=69*CLOCKS_PER_SEC)
//~ #pragma comment(linker, "/stack:200000000")
#pragma GCC optimize("O3")
//~ #pragma GCC optimize("Ofast")
//~ #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
//~ #pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

using namespace __gnu_pbds;
using namespace std;

template <typename T>
using ordered_set =
    tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;

#define sim template < class c
#define ris return * this
#define dor > debug & operator <<
#define eni(x) sim > typename \
  enable_if<sizeof dud<c>(0) x 1, debug&>::type operator<<(c i) {
sim > struct rge { c b, e; };
sim > rge<c> range(c i, c j) { return rge<c>{i, j}; }
sim > auto dud(c* x) -> decltype(cerr << *x, 0);
sim > char dud(...);
struct debug {
#ifdef LOCAL
~debug() { cerr << endl; }
eni(!=) cerr << boolalpha << i; ris; }
eni(==) ris << range(begin(i), end(i)); }
sim, class b dor(pair < b, c > d) {
  ris << "(" << d.first << ", " << d.second << ")";
}
sim dor(rge<c> d) {
  *this << "[";
  for (auto it = d.b; it != d.e; ++it)
    *this << ", " + 2 * (it == d.b) << *it;
  ris << "]";
}
#else
sim dor(const c&) { ris; }
#endif
};
#define imie(...) " [" << #__VA_ARGS__ ": " << (__VA_ARGS__) << "] "

#define shandom_ruffle random_shuffle

using ll=long long;
using pii=pair<int,int>;
using pll=pair<ll,ll>;
using vi=vector<int>;
using vll=vector<ll>;
const int nax=1007;
const ll inf=1e18;

int n, m;

ll odl[nax][nax];

int s, b;
int k;
int g[nax*nax];
ll sil[nax*nax];
ll pal[nax*nax];
ll cen[nax*nax];

vector <pll> bazy[nax];

using T = long long;
struct Flow {
  struct E {
    int dest;
    T orig, *lim, *rev;
  };
  int zr, uj, n = 0;
  vector<unique_ptr<T>> ts;
  vector<vector<E>> graf;
  vector<int> ptr, odl;
  void vert(int v) {
    n = max(n, v + 1);
    graf.resize(n);
    ptr.resize(n);
    odl.resize(n);
  }
  bool iszero(T v) {
    return !v; // Zmienić dla doubli.
  }
  void bfs() {
    fill(odl.begin(), odl.end(), 0);
    vector<int> kol = {zr};
    odl[zr] = 1;
    for (int i = 0; i < (int) kol.size(); i++) {
      for (E& e : graf[kol[i]]) {
        if (!odl[e.dest] and !iszero(*e.lim)) {
          odl[e.dest] = odl[kol[i]] + 1;
          kol.push_back(e.dest);
        }
      }
    }
  }
  T dfs(int v, T lim) {
    if (v == uj) return lim;
    T ret = 0, wez;
    for (int& i = ptr[v]; i < (int) graf[v].size(); i++) {
      E& e = graf[v][i];
      if (odl[e.dest] == odl[v] + 1 and !iszero(*e.lim) and
          !iszero(wez = dfs(e.dest, min(*e.lim, lim)))) {
        ret += wez;
        *e.lim -= wez;
        *e.rev += wez;
        lim -= wez;
        if (iszero(lim)) break;
      }
    }
    return ret;
  }
  void add_edge(int u, int v, T lim, bool bi = false /* bidirectional? */) {
    vert(max(u, v));
    T *a = new T(lim), *b = new T(lim * bi);
    ts.emplace_back(a);
    ts.emplace_back(b);
    graf[u].push_back(E{v, lim,      a, b});
    graf[v].push_back(E{u, lim * bi, b, a});
  }
  T dinic(int zr_, int uj_) {
    zr = zr_; uj = uj_;
    vert(max(zr, uj));
    T ret = 0;
    while (true) {
      bfs();
      fill(ptr.begin(), ptr.end(), 0);
      const T sta = dfs(zr, numeric_limits<T>::max());  // Dla doubli można dać
      if (iszero(sta)) break;                           // infinity() zamiast
      ret += sta;                                       // max().
    }
    return ret;
  }
  vector<int> cut() {
    vector<int> ret;
    bfs();
    for (int i = 0; i < n; i++)
      if (odl[i])
        ret.push_back(i);
    return ret;
  }
  map<pair<int, int>, T> get_flowing() {  // Tam gdzie plynie 0 może nie być
    map<pair<int, int>, T> ret;           // krawędzi.
    for (int i = 0; i < n; i++)
      for (E& e : graf[i])
        if (*e.lim < e.orig)
          ret[make_pair(i, e.dest)] += e.orig - *e.lim;
    for (auto& i : ret) {
      const pair<int, int> rev{i.first.second, i.first.first};
      const T x = min(i.second, ret[rev]);
      i.second -= x;
      ret[rev] -= x;
    }
    return ret;
  }
};

ll best(int v, ll og)
{
	int bsa=0;
	int bsb=(int)bazy[v].size()-1;
	while(bsa<bsb)
	{
		int bss=(bsa+bsb+2)>>1;
		if (bazy[v][bss].second<=og)
			bsa=bss;
		else
			bsb=bss-1;
	}
	return bazy[v][bsa].first;
}

int main()
{
	scanf("%d%d", &n, &m);
	for (int i=1; i<=n; i++)
		for (int j=1; j<=n; j++)
			odl[i][j]=(i!=j)*inf;
	for (int i=1; i<=m; i++)
	{
		int a, b;
		scanf("%d%d", &a, &b);
		if (a!=b)
			odl[a][b]=odl[b][a]=1;
	}
	for (int k=1; k<=n; k++)
		for (int i=1; i<=n; i++)
			for (int j=1; j<=n; j++)
				odl[i][j]=min(odl[i][j], odl[i][k]+odl[k][j]);
	scanf("%d%d%d", &s, &b, &k);
	for (int i=1; i<=s; i++)
		scanf("%d%lld%lld%lld", &g[i], &sil[i], &pal[i], &cen[i]);
	for (int i=1; i<=b; i++)
	{
		int x, y, z;
		scanf("%d%d%d", &x, &y, &z);
		bazy[x].push_back({z, -y});
	}
	for (int i=1; i<=n; i++)
	{
		bazy[i].push_back({-inf, 0});
		sort(bazy[i].begin(), bazy[i].end());
		auto pom=bazy[i];
		bazy[i].clear();
		for (pll j : pom)
		{
			j.second*=-1;
			while(!bazy[i].empty() && bazy[i].back().second>=j.second)
				bazy[i].pop_back();
			bazy[i].push_back(j);
		}
		//~ debug() << i << " " << bazy[i];
	}
	for (int i=1; i<=s; i++)
	{
		ll x=-inf;
		for (int j=1; j<=n; j++)
			if (pal[i]>=odl[g[i]][j])
				x=max(x, best(j, sil[i]));
		cen[i]=x-cen[i];
	}
	ll wyn=0;
	Flow janusz;
	for (int i=1; i<=s; i++)
	{
		if (cen[i]>=0)
		{
			wyn+=cen[i];
			janusz.add_edge(0, i, cen[i]);
		}
		else
		{
			janusz.add_edge(i, s+1, -cen[i]);
		}
	}
	for (int i=1; i<=k; i++)
	{
		int a, b;
		scanf("%d%d", &a, &b);
		//~ debug() << imie(a);
		//~ debug() << imie(b);
		janusz.add_edge(a, b, inf);
	}
	//~ debug() << imie(wyn);
	//~ debug() << imie(range(cen+1, cen+1+s));
	printf("%lld\n", wyn-janusz.dinic(0, s+1));
	return 0;
}

//#pragma GCC optimize("Ofast")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int inf_int = 1e9;
const ll inf_ll = 1e18;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef long double dbl;
#define pb push_back
const double pi = 3.1415926535898;
#define dout if(debug) cout
#define fi first
#define se second
#define sp setprecision
#define sz(a) (int(a.size()))
#define all(a) a.begin(),a.end()
bool debug = 0;
const int MAXN = 1e5 + 100;
const int LOG = 22;
const int mod = 1e9 + 7;
const int MX = 1e6 + 100;
typedef long long li;
const li MOD = 1000000000949747713ll;

int dis[128][128];
int x[MAXN], a[MAXN], f[MAXN], p[MAXN];
int x2[MAXN], d2[MAXN], g2[MAXN];
int s, b;
int n;

ll cost[MAXN];

struct event {
    int type;
    int id;
    int power;

    bool operator<(const event &o) const {
        if (o.power != power)
            return power < o.power;
        return type < o.type;
    }
};

int mx_val[MAXN];

void calc_cost() {
    for (int i = 1; i <= s; ++i) {
        cost[i] = -inf_ll;
    }
    for (int i = 1; i <= n; ++i) {
        mx_val[i] = -1;
    }

    vector<event> events;
    for (int i = 1; i <= s; ++i) {
        event temp;
        temp.type = 1;
        temp.id = i;
        temp.power = a[i];
        events.pb(temp);
    }
    for (int i = 1; i <= b; ++i) {
        event temp;
        temp.type = 0;
        temp.id = i;
        temp.power = d2[i];
        events.pb(temp);
    }
    sort(all(events));

    for (auto &cur:events) {
        int id = cur.id;
        if (cur.type == 0) {
            mx_val[x2[id]] = max(mx_val[x2[id]], g2[id]);
        } else {
            int res = -1;
            for (int to = 1; to <= n; ++to) {
                if (mx_val[to] == -1)
                    continue;
                if (dis[x[id]][to] <= f[id])
                    res = max(res, mx_val[to]);
            }

            if (res == -1)
                continue;
            cost[id] = res - p[id];
        }
    }

    for (int i = 1; i <= s; ++i) {
        dout << i << " -- " << cost[i] << endl;
    }
}

vector<int> g[MAXN];
vector<int> gr[MAXN];

vector<int> g1[MAXN];

int used[MAXN];
vector<int> order;

void def_top_sort(int v) {
    used[v] = 1;
    for (int to:g[v]) {
        if (!used[to]) {
            def_top_sort(to);
        }
    }
    order.pb(v);
}

int comp[MAXN];

void dfs_clr(int v, int clr) {
    comp[v] = clr;
    for (int to:gr[v]) {
        if (!comp[to]) {
            dfs_clr(to, clr);
        }
    }
}

ll new_cost[MAXN];

int k;

void dfs_top(int v) {
    used[v] = 1;
    for (int to:g1[v]) {
        if (!used[to])
            dfs_top(to);
    }
    order.pb(v);
}

int taken[MAXN];

int super_used[MAXN];
int timer = 0;

ll get_val(int v) {
    if (taken[v])
        return 0;
    if(super_used[v] == timer)
        return 0;
    super_used[v] = timer;
    ll res = new_cost[v];
    for (int to:g1[v]) {
        res += get_val(to);
        res = max(res, -inf_ll);
    }
    return res;
}
void dfs_take(int v){
    taken[v] = true;
    for(int to:g1[v]){
        if(!taken[to])
            dfs_take(to);
    }
}

void build_scc() {
    for (int i = 1; i <= k; ++i) {
        int a, b;
        cin >> a >> b;
        g[a].pb(b);
        gr[b].pb(a);
    }
    for (int i = 1; i <= s; ++i) {
        if (!used[i])
            def_top_sort(i);
    }
    reverse(all(order));
    int N = 0;
    for (int v:order) {
        if (comp[v] == 0) {
            ++N;
            dfs_clr(v, N);
        }

    }
    for (int i = 1; i <= s; ++i) {
        dout << "ver " << i << " " << comp[i] << endl;
    }

    set<pii> edges;
    for (int v = 1; v <= s; ++v) {
        for (int to:g[v]) {
            int v1 = comp[v], v2 = comp[to];
            if (v1 == v2)
                continue;
            if (edges.count({v1, v2}))
                continue;
            edges.insert({v1, v2});
            g1[v1].pb(v2);
            dout << "add edge " << v1 << " " << v2 << endl;
        }
    }

    for (int v = 1; v <= s; ++v) {
        new_cost[comp[v]] += cost[v];
        new_cost[comp[v]] = max(new_cost[comp[v]], -inf_ll);
    }

    order.clear();
    memset(used, 0, sizeof used);

    for (int v = 1; v <= N; ++v) {
        if (!used[v])
            dfs_top(v);
    }

    ll ans = 0;
    for (int v:order) {
        timer++;
        ll val = get_val(v);
        if(val > 0){
            ans += val;
            dfs_take(v);
        }

    }
    cout << ans;

}

void solve() {
    int m;
    cin >> n >> m;
    for (int i = 1; i <= n; ++i) {
        for (int e = 1; e <= n; ++e) {
            dis[i][e] = inf_int;
        }
        dis[i][i] = 0;
    }
    for (int i = 1; i <= m; ++i) {
        int a, b;
        cin >> a >> b;
        dis[a][b] = 1;
        dis[b][a] = 1;
    }
    for (int k = 1; k <= n; ++k) {
        for (int i = 1; i <= n; ++i) {
            for (int e = 1; e <= n; ++e) {
                dis[i][e] = min(dis[i][e], dis[i][k] + dis[k][e]);
            }
        }
    }

    cin >> s >> b >> k;
    for (int i = 1; i <= s; ++i) {
        cin >> x[i] >> a[i] >> f[i] >> p[i];
    }
    for (int i = 1; i <= b; ++i) {
        cin >> x2[i] >> d2[i] >> g2[i];
    }

    calc_cost();
    build_scc();

}

signed main() {
#ifdef zxc
    debug = 0;
    freopen("../input.txt", "r", stdin);
    //freopen("../output.txt", "w", stdout);
#else
    //freopen("roboherd.in", "r", stdin);
    //freopen("roboherd.out", "w", stdout);

#endif //zxc
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    cout.setf(ios::fixed);
    cout.precision(20);

    int t = 1;
    while (t--)
        solve();
    if (debug)
        cerr << endl << "time : " << (1.0 * clock() / CLOCKS_PER_SEC) << endl;
}

#pragma GCC optimize("O3")

#include <bits/stdc++.h>

using namespace std;
typedef long double ld;
typedef long long ll;
int n, m;
int s, b, k;
const int N = 101;
const int M = 100001;
const ll inf = 1e14;
int a[N][N];

ll cost[M];
int vertex[M], fuel[M], damage[M];
vector<pair<ll, ll> > bases[N];
int st[M], dist[M];

struct edge {
    int to, lnk;
    ll flow;
};

vector<edge> ed[M];

void add_edge(int u, int v, ll flow) {
  ed[u].push_back(edge{v, (int)ed[v].size(), flow});
  ed[v].push_back(edge{u, (int)ed[u].size() - 1, 0});
}

bool bfs(int s, int t) {
  dist[s] = 0;
  queue<int> q;
  q.push(s);
  bool fnd = false;
  while (!q.empty()) {
    int v = q.front();
    if (v == t) {
      fnd = true;
    }
    for (auto to : ed[v]) {
      if (to.flow == 0) {
        continue;
      }
      if (dist[to.to] <= dist[v] + 1) {
        continue;
      }
      dist[to.to] = dist[v] + 1;
      q.push(to.to);
    }
    q.pop();
  }
  return fnd;
}

ll dfs(int v, int t, ll p) {
  if (v == t) {
    return p;
  }
  for (; st[v] < ed[v].size(); st[v]++) {
    auto& to = ed[v][st[v]];
    if (to.flow == 0) {
      continue;
    }
    if (dist[to.to] != dist[v] + 1) {
      continue;
    }
    ll q = dfs(to.to, t, min(p, to.flow));
    if (q == 0) {
      continue;
    }
    to.flow -= q;
    ed[to.to][to.lnk].flow += q;
    return q;
  }
  return 0;
}

ll flow() {
  ll ans = 0;
  while (1) {
    for (int i = 0; i <= s + 1; i++) {
      st[i] = 0;
      dist[i] = s + 3;
    }
    if (!bfs(0, s + 1)) {
      break;
    }
    ll p = dfs(0, s + 1, inf);
    while (p != 0) {
      ans += p;
      p = dfs(0, s + 1, inf);
    }
  }
  return ans;
}

int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(nullptr);
  //freopen("input.txt", "r", stdin);
  cin >> n >> m;
  for (int i = 0; i < m; i++) {
    int u, v;
    cin >> u >> v;
    a[u][v] = 1;
    a[v][u] = 1;
  }
  for (int k = 1; k <= n; k++) {
    for (int i = 1; i <= n; i++) {
      for (int j = 1; j <= n; j++) {
        if (a[i][k] == 0) {
          continue;
        }
        if (a[k][j] == 0) {
          continue;
        }
        if (a[i][j] == 0) {
          a[i][j] = a[i][k] + a[k][j];
        }
        a[i][j] = min(a[i][j], a[i][k] + a[k][j]);
      }
    }
  }
  cin >> s >> b >> k;
  for (int i = 1; i <= s; i++) {
    cin >> vertex[i] >> damage[i] >> fuel[i] >> cost[i];
  }

  for (int i = 0; i < b; i++) {
    int v, d, g;
    cin >> v >> d >> g;
    bases[v].emplace_back(d, g);
  }

  for (int i = 1; i <= n; i++) {
    sort(bases[i].begin(), bases[i].end());
    ll cur_mx = -inf;
    for (auto& it : bases[i]) {
      cur_mx = max(it.second, cur_mx);
      it.second = cur_mx;
    }
  }

  for (int i = 1; i <= s; i++) {
    cost[i] = -cost[i];
    ll mx = -inf;
    for (int v = 1; v <= n; v++) {
      if (a[vertex[i]][v] > fuel[i]) {
        continue;
      }
      auto it = lower_bound(bases[v].begin(), bases[v].end(), make_pair(ll(damage[i] + 1), -1ll));
      if (it == bases[v].begin()) {
        continue;
      }
      it--;
      mx = max(mx, it->second);
    }
    cost[i] += mx;
  }
  ll positive_sum = 0;
  for (int i = 1; i <= s; i++) {
    positive_sum += abs(max(cost[i], 0ll));
    if (cost[i] > 0) {
      add_edge(0, i, cost[i]);
    } else if (cost[i] < 0) {
      add_edge(i, s + 1, -cost[i]);
    }
  }
  for (int i = 0; i < k; i++) {
    int u, v;
    cin >> u >> v;
    add_edge(u, v, inf);
  }
  cout << positive_sum - flow() << "\n";
  return 0;
}

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef pair <int, int> ii;

const int Maxn = 105;
const int Inf = 1000000000;
const int Maxs = 100005;

int n, m;
int dist[Maxn][Maxn];
int S, B, K;
int ax[Maxs], ay[Maxs], az[Maxs], ap[Maxs];
deque <ii> inbase[Maxn];
bool fall[Maxs];
int gain[Maxs];
vector <int> rneigh[Maxs], neigh[Maxs];
ll res;

const int MAXN = 2005;
const int INF = 1000000000;

struct edge {
	int a, b, cap, flow;
};

int N, s, t, d[MAXN], ptr[MAXN], q[MAXN];
vector<edge> e;
vector<int> g[MAXN];

void add_edge (int a, int b, int cap) {
	edge e1 = { a, b, cap, 0 };
	edge e2 = { b, a, 0, 0 };
	g[a].push_back ((int) e.size());
	e.push_back (e1);
	g[b].push_back ((int) e.size());
	e.push_back (e2);
}

bool bfs() {
	int qh=0, qt=0;
	q[qt++] = s;
	memset (d, -1, N * sizeof d[0]);
	d[s] = 0;
	while (qh < qt && d[t] == -1) {
		int v = q[qh++];
		for (size_t i=0; i<g[v].size(); ++i) {
			int id = g[v][i],
				to = e[id].b;
			if (d[to] == -1 && e[id].flow < e[id].cap) {
				q[qt++] = to;
				d[to] = d[v] + 1;
			}
		}
	}
	return d[t] != -1;
}

int dfs (int v, int flow) {
	if (!flow)  return 0;
	if (v == t)  return flow;
	for (; ptr[v]<(int)g[v].size(); ++ptr[v]) {
		int id = g[v][ptr[v]],
			to = e[id].b;
		if (d[to] != d[v] + 1)  continue;
		int pushed = dfs (to, min (flow, e[id].cap - e[id].flow));
		if (pushed) {
			e[id].flow += pushed;
			e[id^1].flow -= pushed;
			return pushed;
		}
	}
	return 0;
}

ll dinic() {
	ll flow = 0;
	for (;;) {
		if (!bfs())  break;
		memset (ptr, 0, N * sizeof ptr[0]);
		while (int pushed = dfs (s, INF))
			flow += pushed;
	}
	return flow;
}

bool Less(const ii &a, const ii &b)
{
    if (a.first != b.first) return a.first < b.first;
    return a.second > b.second;
}

int main()
{
    scanf("%d %d", &n, &m);
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= n; j++)
            if (i != j) dist[i][j] = Inf;
    for (int i = 0; i < m; i++) {
        int a, b; scanf("%d %d", &a, &b);
        if (a != b) dist[a][b] = dist[b][a] = 1;
    }
    for (int k = 1; k <= n; k++)
        for (int i = 1; i <= n; i++)
            for (int j = 1; j <= n; j++)
                dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
    scanf("%d %d %d", &S, &B, &K);
    vector <ii> byattack;
    for (int i = 0; i < S; i++) {
        scanf("%d %d %d %d", &ax[i], &ay[i], &az[i], &ap[i]);
        byattack.push_back(ii(ay[i], i));
    }
    sort(byattack.begin(), byattack.end());
    for (int i = 0; i < B; i++) {
        int x, d, g; scanf("%d %d %d", &x, &d, &g);
        inbase[x].push_back(ii(d, g));
    }
    for (int i = 1; i <= n; i++) {
        sort(inbase[i].begin(), inbase[i].end(), Less);
        deque <ii> tmp;
        int lst = -1;
        for (int j = 0; j < inbase[i].size(); j++) {
            ii p = inbase[i][j];
            if (p.second > lst) {
                tmp.push_back(p);
                lst = p.second;
            }
        }
        inbase[i] = tmp;
    }
    for (int i = 0; i < byattack.size(); i++) {
        int ind = byattack[i].second;
        int tk = -1;
        for (int j = 1; j <= n; j++) if (dist[ax[ind]][j] <= az[ind]) {
            while (inbase[j].size() >= 2 && inbase[j][1].first <= ay[ind])
                inbase[j].pop_front();
            if (inbase[j].empty()) continue;
            if (inbase[j][0].first <= ay[ind])
                tk = max(tk, inbase[j][0].second);
        }
        if (tk == -1) fall[ind] = true;
        else gain[ind] = tk - ap[ind];
    }
    for (int i = 0; i < K; i++) {
        int a, b; scanf("%d %d", &a, &b); a--; b--;
        neigh[a].push_back(b);
        rneigh[b].push_back(a);
    }
    vector <int> Q;
    for (int i = 0; i < S; i++)
        if (fall[i]) Q.push_back(i);
    for (int i = 0; i < Q.size(); i++) {
        int v = Q[i];
        for (int j = 0; j < rneigh[v].size(); j++) {
            int u = rneigh[v][j];
            if (!fall[u]) { fall[u] = true; Q.push_back(u); }
        }
    }
    vector <int> un;
    for (int i = 0; i < S; i++) if (!fall[i])
        if (rneigh[i].empty() && neigh[i].empty())
            res += max(gain[i], 0);
        else un.push_back(i);
    N = int(un.size()) + 2;
    s = 0, t = N - 1;
    for (int i = 0; i < un.size(); i++) {
        int v = un[i];
        if (gain[v] >= 0) { res += gain[v]; add_edge(s, i + 1, gain[v]); }
        else add_edge(i + 1, t, -gain[v]);
        for (int j = 0; j < neigh[v].size(); j++) {
            int u = neigh[v][j];
            int ind = lower_bound(un.begin(), un.end(), u) - un.begin();
            add_edge(i + 1, ind + 1, INF);
        }
    }
    res -= dinic();
    cout << res << endl;
    return 0;
}

#include <bits/stdc++.h>

using namespace std;

#define endl '\n'

typedef long long int64;
typedef pair<int,int> pii;
typedef vector<int> vi;

const double eps = 1e-9;
const int64 oo = 0x3f3f3f3f3f3f3f3f;
const int mod = 1000000007;

int dist[128][128];

struct ss {
    int x, a, f, p;
} SS[100000];

int64 best[100000];
vector<pii> BASE[128];

template<typename flow_type>
struct dinic
{
	struct edge
	{
		size_t src, dst, rev;
		flow_type flow, cap;
	};

	int n;
	vector<vector<edge>> adj;

	dinic(int n) : n(n), adj(n), level(n), q(n), it(n) {}

	void add_edge(size_t src, size_t dst, flow_type cap, flow_type rcap = 0)
	{
		adj[src].push_back({src, dst, adj[dst].size(), 0, cap});
		if (src == dst) adj[src].back().rev++;
		adj[dst].push_back({dst, src, adj[src].size() - 1, 0, rcap});
	}

	vector<int> level, q, it;

	bool bfs(int source, int sink)
	{
		fill(level.begin(), level.end(), -1);
		for (int qf = level[q[0] = sink] = 0, qb = 1; qf < qb; ++qf)
		{
			sink = q[qf];
			for (edge &e : adj[sink])
			{
				edge &r = adj[e.dst][e.rev];
				if (r.flow < r.cap && level[e.dst] == -1)
					level[q[qb++] = e.dst] = 1 + level[sink];
			}
		}
		return level[source] != -1;
	}

	flow_type augment(int source, int sink, flow_type flow)
	{
		if (source == sink) return flow;
		for (; it[source] != adj[source].size(); ++it[source])
		{
			edge &e = adj[source][it[source]];
			if (e.flow < e.cap && level[e.dst] + 1 == level[source])
			{
				flow_type delta = augment(e.dst, sink,
								  min(flow, e.cap - e.flow));
				if (delta > 0)
				{
					e.flow += delta;
					adj[e.dst][e.rev].flow -= delta;
					return delta;
				}
			}
		}
		return 0;
	}

	flow_type max_flow(int source, int sink)
	{
		for (int u = 0; u < n; ++u)
			for (edge &e : adj[u]) e.flow = 0;
		flow_type flow = 0;
		flow_type oo = numeric_limits<flow_type>::max();

		while (bfs(source, sink))
		{
			fill(it.begin(), it.end(), 0);
			for (flow_type f; (f = augment(source, sink, oo)) > 0;)
				flow += f;

		} // level[u] = -1 => source side of min cut
		return flow;
	}
};

int main(){
    ios_base::sync_with_stdio(0);
    cin.tie(0);

    int n, m;
    cin >> n >> m;

    memset(dist, 0x3f, sizeof dist);

    for (int i = 0; i < m; ++i){
        int u, v;
        cin >> u >> v;
        u--; v--;
        dist[u][v] = dist[v][u] = 1;
    }

    for (int i = 0; i < n; ++i)
        dist[i][i] = 0;

    for (int k = 0; k < n; ++k)
        for (int i = 0; i < n; ++i)
            for (int j = 0; j < n; ++j){
                dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
            }

    int s, b, k;
    cin >> s >> b >> k;

    for (int i = 0; i < s; ++i){
        cin >> SS[i].x >> SS[i].a >> SS[i].f >> SS[i].p;
        SS[i].x--;
        best[i] = -oo;
    }

    for (int i = 0; i < b   ; ++i){
        int x, d, g;
        cin >> x >> d >> g;
        x--;

        BASE[x].push_back({d, g});
    }

    for (int i = 0; i < n; ++i){
        sort(BASE[i].begin(), BASE[i].end());

        vector<pii> inc;

        // cout << "BASE: " << i + 1 << endl;

        for (auto p : BASE[i]) {
            if (inc.empty() || p.second > inc.back().second){
                inc.push_back(p);
                // cout << p.first << " " << p.second << endl;
            }
        }

        for (int j = 0; j < s; ++j){
            if (SS[j].f < dist[SS[j].x][i])
                continue;

            int p = upper_bound(inc.begin(), inc.end(), pii(SS[j].a, mod)) - inc.begin();

            if (p) {
                --p;
                best[j] = max(best[j], 1LL * (inc[p].second - SS[j].p));
            }
        }
    }

    dinic<int64> closure(s + 2);

    for (int i = 0; i < k; ++i){
        int u, v; cin >> u >> v;
        u--; v--;

        closure.add_edge(u + 2, v + 2, oo);
    }

    int64 positive = 0;

    for (int i = 0; i < s; ++i){
        // cout << i + 1 << " " << best[i] << endl;

        if (best[i] >= 0){
            positive += best[i];
            closure.add_edge(0, i + 2, best[i]);
        } else {
            closure.add_edge(i + 2, 1, -best[i]);
        }
    }

    int64 cut = closure.max_flow(0, 1);

    cout << positive - cut << endl;

    return 0;
}

#include <bits/stdc++.h>
using namespace std;
//#pragma GCC optimize("Ofast")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")

#define ms(s, n) memset(s, n, sizeof(s))
#define FOR(i, a, b) for (int i = (a); i < (b); ++i)
#define FORd(i, a, b) for (int i = (a) - 1; i >= (b); --i)
#define FORall(it, a) for (__typeof((a).begin()) it = (a).begin(); it != (a).end(); it++)
#define sz(a) int((a).size())
#define present(t, x) (t.find(x) != t.end())
#define all(a) (a).begin(), (a).end()
#define uni(a) (a).erase(unique(all(a)), (a).end())
#define pb push_back
#define pf push_front
#define mp make_pair
#define fi first
#define se second
#define prec(n) fixed<<setprecision(n)
#define bit(n, i) (((n) >> (i)) & 1)
#define bitcount(n) __builtin_popcountll(n)
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef pair<int, int> pi;
typedef vector<int> vi;
typedef vector<pi> vii;
const int MOD = (int) 1e9 + 7;
const int FFTMOD = 119 << 23 | 1;
const int INF = (int) 1e9 + 23111992;
const ll LINF = (ll) 1e18 + 23111992;
const ld PI = acos((ld) -1);
const ld EPS = 1e-9;
inline ll gcd(ll a, ll b) {ll r; while (b) {r = a % b; a = b; b = r;} return a;}
inline ll lcm(ll a, ll b) {return a / gcd(a, b) * b;}
inline ll fpow(ll n, ll k, int p = MOD) {ll r = 1; for (; k; k >>= 1) {if (k & 1) r = r * n % p; n = n * n % p;} return r;}
template<class T> inline int chkmin(T& a, const T& val) {return val < a ? a = val, 1 : 0;}
template<class T> inline int chkmax(T& a, const T& val) {return a < val ? a = val, 1 : 0;}
inline ull isqrt(ull k) {ull r = sqrt(k) + 1; while (r * r > k) r--; return r;}
inline ll icbrt(ll k) {ll r = cbrt(k) + 1; while (r * r * r > k) r--; return r;}
inline void addmod(int& a, int val, int p = MOD) {if ((a = (a + val)) >= p) a -= p;}
inline void submod(int& a, int val, int p = MOD) {if ((a = (a - val)) < 0) a += p;}
inline int mult(int a, int b, int p = MOD) {return (ll) a * b % p;}
inline int inv(int a, int p = MOD) {return fpow(a, p - 2, p);}
inline int sign(ld x) {return x < -EPS ? -1 : x > +EPS;}
inline int sign(ld x, ld y) {return sign(x - y);}
mt19937 mt(chrono::high_resolution_clock::now().time_since_epoch().count());
inline int mrand() {return abs((int) mt());}
#define db(x) cerr << "[" << #x << ": " << (x) << "] ";
#define endln cerr << "\n";

#define MF Maxflow
#define flow_t long long
const flow_t foo = (flow_t) 1e18;
namespace Maxflow {
    const int maxv = 2e5 + 5;
    const int maxe = 1e7 + 5;
    int n, s, t, E;
    int adj[maxe], nxt[maxe], lst[maxv], ptr[maxv], lev[maxv], que[maxv];
    flow_t flw[maxe], cap[maxe];
    void init(int nn, int ss, int tt) {
        n = nn, s = ss, t = tt, E = 0;
        fill_n(lst, n, -1);
    }
    void add(int u, int v, flow_t c1, flow_t c2) {
        adj[E] = v, flw[E] = 0, cap[E] = c1, nxt[E] = lst[u], lst[u] = E++;
        adj[E] = u, flw[E] = 0, cap[E] = c2, nxt[E] = lst[v], lst[v] = E++;
    }
    int bfs() {
        fill_n(lev, n, 0), lev[s] = 1;
        int qsize = 0;
        que[qsize++] = s;
        for (int i = 0; i < qsize; i++) {
            for (int u = que[i], e = lst[u]; ~e; e = nxt[e]) {
                int v = adj[e];
                if (flw[e] < cap[e] && !lev[v]) {
                    lev[v] = lev[u] + 1;
                    que[qsize++] = v;
                }
            }
        }
        return lev[t];
    }
    flow_t dfs(int u, flow_t bot) {
        if (u == t) return bot;
        for (int& e = ptr[u]; ~e; e = nxt[e]) {
            int v = adj[e];
            flow_t delta = 0;
            if (lev[v] == lev[u] + 1 && flw[e] < cap[e] && (delta = dfs(v, min(bot, cap[e] - flw[e]))) > 0) {
                flw[e] += delta; flw[e ^ 1] -= delta;
                return delta;
            }
        }
        return 0;
    }
    flow_t maxflow(int ss = -1, int tt = -1) {
        if (~ss) s = ss;
        if (~tt) t = tt;
        fill_n(flw, E, 0);
        flow_t total = 0;
        while (bfs()) {
            for (int i = 0; i < n; i++) ptr[i] = lst[i];
            for (flow_t delta = dfs(s, foo); delta > 0; delta = dfs(s, foo)) total += delta;
        }
        return total;
    }
    vector<pair<pair<int, int>, flow_t> > gomory_hu() {
        vector<pair<pair<int, int>, flow_t> > tree;
        vector<int> p(n);
        for (int u = 1; u < n; u++) {
            tree.push_back(make_pair(make_pair(p[u], u), maxflow(u, p[u])));
            for (int v = u + 1; v < n; ++v) {
                if (lev[v] && p[v] == p[u]) {
                    p[v] = u;
                }
            }
        }
        return tree;
    }
}

void chemthan() {
    int n, m; cin >> n >> m;
    vector<vi> d(n, vi(n, INF));
    FOR(i, 0, n) d[i][i] = 0;
    FOR(i, 0, m) {
        int u, v; cin >> u >> v; u--, v--;
        if (u ^ v) {
            d[u][v] = d[v][u] = 1;
        }
    }
    FOR(w, 0, n) FOR(u, 0, n) FOR(v, 0, n) chkmin(d[u][v], d[u][w] + d[w][v]);
    int s, b, k; cin >> s >> b >> k;
    vi x(s), a(s), f(s), p(s);
    FOR(i, 0, s) {
        cin >> x[i] >> a[i] >> f[i] >> p[i], x[i]--;
    }
    vector<vii> g(n);
    FOR(i, 0, b) {
        int x, d, gg; cin >> x >> d >> gg, x--;
        g[x].pb(mp(d, gg));
    }
    FOR(u, 0, n) {
        sort(all(g[u]));
        FOR(i, 1, sz(g[u])) {
            chkmax(g[u][i].se, g[u][i - 1].se);
        }
    }
    vi c(s), cc(s);
    FOR(i, 0, s) {
        FOR(u, 0, n) if (d[x[i]][u] <= f[i]) {
            int k = upper_bound(all(g[u]), mp(a[i], INF)) - g[u].begin() - 1;
            if (0 <= k) {
                chkmax(c[i], g[u][k].se);
                cc[i] = 1;
            }
        }
        c[i] -= p[i];
    }
    int tot = s, S = tot++, t = tot++;
    MF::init(tot, S, t);
    long long res = 0;
    FOR(i, 0, s) {
        if (0 <= c[i]) {
            MF::add(S, i, c[i], 0);
            res += c[i];
        }
        else {
            MF::add(i, t, -c[i], 0);
        }
    }
    FOR(i, 0, k) {
        int u, v; cin >> u >> v; u--, v--;
        MF::add(u, v, LINF, 0);
    }
    FOR(i, 0, s) {
        if (!cc[i]) {
            MF::add(i, t, LINF, 0);
        }
    }
    cout << res - MF::maxflow() << "\n";
}

int main(int argc, char* argv[]) {
    ios_base::sync_with_stdio(0), cin.tie(0);
    if (argc > 1) {
        assert(freopen(argv[1], "r", stdin));
    }
    if (argc > 2) {
        assert(freopen(argv[2], "wb", stdout));
    }
    chemthan();
    cerr << "\nTime elapsed: " << 1000 * clock() / CLOCKS_PER_SEC << "ms\n";
    return 0;
}

#include <bits/stdc++.h>
using namespace std;

const int maxn = 100 + 5;
const int maxs = 1e5 + 5;
vector<int> gr[maxs], rg[maxs], sg[maxs];
int x[maxs], a[maxs], f[maxs], p[maxs];
int y[maxs], d[maxs], g[maxs];
int w[maxn][maxn], mg[maxn];
int topo[maxs], scc[maxs], uf[maxs];
long long pf[maxs], sum[maxs], ans[maxs];
long long opt[maxs];
bool ok[maxs], used[maxs];
bool sok[maxs];

void build(int n, int s, int b) {
    vector<int> vs(s), vb(b);
    iota(vs.begin(), vs.end(), 0);
    iota(vb.begin(), vb.end(), 0);
    sort(vs.begin(), vs.end(), [&](int i, int j) {
        return a[i] < a[j];
    });
    sort(vb.begin(), vb.end(), [&](int i, int j) {
        return d[i] < d[j];
    });

    for (int i = 0; i < n; ++i) mg[i] = -1;

    for (int i = 0, j = 0; i < s; ++i) {
        while (j < b && d[vb[j]] <= a[vs[i]]) {
            mg[y[vb[j]]] = max(mg[y[vb[j]]], g[vb[j]]);
            ++j;
        }
        int res = -1;
        for (int k = 0; k < n; ++k) {
            if (w[x[vs[i]]][k] <= f[vs[i]])
                res = max(res, mg[k]);
        }
        if (res == -1) ok[vs[i]] = false;
        else ok[vs[i]] = true, pf[vs[i]] = res - p[vs[i]];
    }
}

void dfs(int x) {
    static int sz = 0;
    used[x] = true;
    for (int i = 0; i < (int)gr[x].size(); ++i) {
        int u = gr[x][i];
        if (!used[u]) dfs(u);
    }
    topo[sz++] = x;
}

void rdfs(int x, int s) {
    scc[x] = s;
    for (int i = 0; i < (int)rg[x].size(); ++i) {
        int u = rg[x][i];
        if (scc[u] == -1) rdfs(u, s);
    }
}

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

void merge(int x, int y) {
    uf[find(x)] = find(y);
}

vector<int> walk;

void dfs3(int x) {
    walk.push_back(x);
    used[x] = true;
    for (int i = 0; i < (int)sg[x].size(); ++i) {
        int u = sg[x][i];
        if (used[u]) continue;
        dfs3(u);
    }
}

struct dinic {
    static const int maxn = maxs;
    static const long long inf = 1e18;
    struct edge {
        int dest, rev;
        long long cap;
        edge(int d, long long c, int r): dest(d), cap(c), rev(r) {}
    };
    vector<edge> g[maxn];
    int qu[maxn], ql, qr;
    int lev[maxn];
    void init() {
        for (int i = 0; i < maxn; ++i)
            g[i].clear();
    }
    void add_edge(int a, int b, long long c) {
        g[a].emplace_back(b, c, g[b].size() - 0);
        g[b].emplace_back(a, 0, g[a].size() - 1);
    }
    bool bfs(int s, int t) {
        memset(lev, -1, sizeof(lev));
        lev[s] = 0;
        ql = qr = 0;
        qu[qr++] = s;
        while (ql < qr) {
            int x = qu[ql++];
            for (edge &e : g[x]) if (lev[e.dest] == -1 && e.cap > 0) {
                lev[e.dest] = lev[x] + 1;
                qu[qr++] = e.dest;
            }
        }
        return lev[t] != -1;
    }
    long long dfs(int x, int t, long long flow) {
        if (x == t) return flow;
        long long res = 0;
        for (edge &e : g[x]) if (e.cap > 0 && lev[e.dest] == lev[x] + 1) {
            long long f = dfs(e.dest, t, min(e.cap, flow - res));
            res += f;
            e.cap -= f;
            g[e.dest][e.rev].cap += f;
        }
        if (res == 0) lev[x] = -1;
        return res;
    }
    long long operator()(int s, int t) {
        long long flow = 0;
        for (; bfs(s, t); flow += dfs(s, t, inf));
        return flow;
    }
};

int main() {
    int n, m; scanf("%d%d", &n, &m);
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < n; ++j)
            w[i][j] = i == j ? 0 : 1e8;
    }
    for (int i = 0; i < m; ++i) {
        int u, v; scanf("%d%d", &u, &v);
        --u, --v;
        if (u == v) continue;
        w[u][v] = w[v][u] = 1;
    }

    for (int k = 0; k < n; ++k) {
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < n; ++j)
                w[i][j] = min(w[i][j], w[i][k] + w[k][j]);
        }
    }

    int s, b, k; scanf("%d%d%d", &s, &b, &k);
    for (int i = 0; i < s; ++i) {
        scanf("%d%d%d%d", &x[i], &a[i], &f[i], &p[i]);
        --x[i];
    }
    for (int i = 0; i < b; ++i) {
        scanf("%d%d%d", &y[i], &d[i], &g[i]);
        --y[i];
    }

    build(n, s, b);
    dinic flow;
    long long sum = 0;
    for (int i = 0; i < s; ++i) {
        if (!ok[i]) {
            flow.add_edge(i, s + 1, 2e14);
            continue;
        }
        if (pf[i] >= 0) {
            sum += pf[i];
            flow.add_edge(s, i, pf[i]);
        } else {
            flow.add_edge(i, s + 1, -pf[i]);
        }
    }

    while (k--) {
        int u, v; scanf("%d%d", &u, &v);
        --u, --v;
        flow.add_edge(u, v, 2e14);
    }

    printf("%lld\n", sum - flow(s, s + 1));

    /*
    for (int i = 0; i < s; ++i) {
        if (!used[i]) dfs(i);
    }

    memset(scc, -1, sizeof(scc));
    int sz = 0;
    for (int i = s - 1; i >= 0; --i) {
        if (scc[topo[i]] == -1) {
            rdfs(topo[i], sz);
            ++sz;
        }
    }

    for (int i = 0; i < sz; ++i) {
        sok[i] = true;
        uf[i] = i;
    }

    for (int i = 0; i < s; ++i) {
        sok[scc[i]] &= ok[i];
        sum[scc[i]] += pf[i];
        for (int j = 0; j < (int)gr[i].size(); ++j) {
            int u = gr[i][j];
            if (scc[i] != scc[u]) {
                sg[scc[i]].push_back(scc[u]);
                merge(scc[i], scc[u]);
            }
        }
    }

    for (int i = 0; i < sz; ++i) {
        sort(sg[i].begin(), sg[i].end());
        sg[i].resize(unique(sg[i].begin(), sg[i].end()) - sg[i].begin());
    }

    memset(used, false, sizeof(used));
    for (int i = 0; i < sz; ++i) opt[i] = -1e18;
    for (int i = 0; i < sz; ++i) {
        walk.clear();
        dfs3(i);
        bool tok = true;
        long long su = 0;
        for (int j = 0; j < (int)walk.size(); ++j) {
            int u = walk[j];
            tok |= sok[u];
            su += sum[u];
            used[u] = false;
        }
        if (tok) opt[find(i)] = max(opt[find(i)], su);
    }

    long long ans = 0;
    for (int i = 0; i < sz; ++i) {
        if (find(i) == i)
            ans += max(0ll, opt[i]);
    } */

    // printf("%lld\n", ans);
    return 0;
}

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int INF = 1e17;
const int maxn = 100015;
const int maxm = 1000005;
int g[105][105];
int num[maxn];
int id[maxn];
int cnt;
void floyed(int n){
    for(int k = 1; k <= n; k++){
        for(int i = 1; i <= n; i++){
            for(int j = 1; j <= n; j++){
                g[i][j] = min(g[i][j], g[i][k]+g[k][j]);
            }
        }
    }
};
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
    while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
struct Edge{
    int to,next,cap,flow;
}edge[maxm];
int tol,head[maxn];
void init()
{
    tol=2;
    memset(head,-1,sizeof(head));
}
void addedge(int u,int v,int w,int rw=0)
{
    edge[tol].to=v;edge[tol].cap=w;edge[tol].flow=0;
    edge[tol].next=head[u];head[u]=tol++;
    edge[tol].to=u;edge[tol].cap=rw;edge[tol].flow=0;
    edge[tol].next=head[v];head[v]=tol++;
}
int Q[maxn];
int dep[maxn],cur[maxn],sta[maxn];
bool bfs(int s,int t,int n)
{
    int front=0,tail=0;
    memset(dep,-1,sizeof(dep[0])*(n+1));
    dep[s]=0;
    Q[tail++]=s;
    while(front<tail){
        int u=Q[front++];
        for(int i=head[u];i!=-1;i=edge[i].next){
            int v=edge[i].to;
            if(edge[i].cap>edge[i].flow&&dep[v]==-1){
                dep[v]=dep[u]+1;
                if(v==t){
                    return true;
                }
                Q[tail++]=v;
            }
        }
    }
    return false;
}
long long dinic(int s,int t,int n)
{
    long long maxflow=0;
    while(bfs(s,t,n)){
        for(int i=0;i<n;i++){
            cur[i]=head[i];
        }
        int u=s,tail=0;
        while(cur[s]!=-1){
            if(u==t){
                int tp=INF;
                for(int i=tail-1;i>=0;i--){
                    tp=min(tp,edge[sta[i]].cap-edge[sta[i]].flow);
                }
                maxflow+=tp;
                for(int i=tail-1;i>=0;i--){
                    edge[sta[i]].flow+=tp;
                    edge[sta[i]^1].flow-=tp;
                    if(edge[sta[i]].cap-edge[sta[i]].flow==0){
                        tail=i;
                    }
                }
                u=edge[sta[tail]^1].to;
            }else if(cur[u]!=-1&&edge[cur[u]].cap>edge[cur[u]].flow&&dep[u]+1==dep[edge[cur[u]].to]){
                sta[tail++]=cur[u];
                u=edge[cur[u]].to;
            }else{
                while(u!=s&&cur[u]==-1){
                    u=edge[sta[--tail]^1].to;
                }
                cur[u]=edge[cur[u]].next;
            }
        }
    }
    return maxflow;
}
//vector<int>fuck[100005];
int fuckacm[100005];
int ps[105];
int shipos[maxn], atk[maxn], f[maxn], p[maxn], baspos[maxn], d[maxn], gold[maxn], val[maxn], D[maxn];
bool svis[maxn];
#define pii pair<int,int>
vector<pii> v1[105];
int e[maxn][2];
bool cmp(int x, int y){
    return atk[x] < atk[y];
}
long long ans = 0;
signed main(){
    int n, m, u, v, s, b, k;
    n = read(), m = read();
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n; j++){
            if(i==j) g[i][j] = 0;
            else g[i][j] = g[j][i] = INF;
        }
    }
    for(int i = 1; i <= m; i++){
        u = read(), v = read();
        g[u][v] = g[v][u] = 1;
    }
    floyed(n);
    s = read(), b = read(), k = read();
    for(int i = 1; i <= s; i++){
        shipos[i] = read(), atk[i] = read(), f[i] = read(), p[i] = read();
        id[i] = i;
    }
    for(int i = 1; i <= b; i++){
        baspos[i] = read(), d[i] = read(), gold[i] = read();
        v1[baspos[i]].emplace_back(pii(d[i], gold[i]));
    }
    sort(id+1, id+1+s, cmp);
    for(int i = 1; i <= n; i++){
        sort(v1[i].begin(), v1[i].end()); ps[i] = 0;
        for(int j = 1; j < v1[i].size(); j++){
            v1[i][j].second = max(v1[i][j].second, v1[i][j-1].second);
        }
    }
    for(int I = 1; I <= s; I++){
        int i = id[I];
        int ma = -INF;
        for(int j = 1; j <= n; j++){
            if(g[shipos[i]][j] <= f[i]){
                if(v1[j].empty()) continue;
                while(ps[j] < v1[j].size()-1 && v1[j][ps[j]+1].first <= atk[i]) ps[j]++;
                if(v1[j][ps[j]].first <= atk[i]) ma = max(ma, v1[j][ps[j]].second);
            }
        }
        val[i] = ma-p[i];
        if(val[i]>0) ans += val[i];
    }
    for(int i =  1; i <= k; i++){
        e[i][0] = read(), e[i][1] = read();
        D[e[i][0]]++, D[e[i][1]]++;
    }
    int S = 2015+1, T = S+1;
    init();
    for(int i = 1; i <= s; i++){
        if(D[i]) id[i] = ++cnt;
    }
    for(int i = 1; i <= s; i++){
        if(D[i]){
            if(val[i] > 0) addedge(S, id[i], val[i]);
            else addedge(id[i], T, -val[i]);
        }
    }
    for(int i = 1; i <= k; i++){
        addedge(id[e[i][0]], id[e[i][1]], INF);
    }
    ans -= dinic(S, T, T+1);
    cout << ans;
    return 0;
}

#include <iostream>
#include <fstream>
#include <numeric>
#include <iomanip>
#include <cstring>
#include <string>
#include <algorithm>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <deque>

#define int ll
#define sz(a) (int)((a).size())
#define all(a) (a).begin(), (a).end()
#define pb push_back

using namespace std; using ll = long long; using vi = vector<int>; using pii = pair<int, int>; using ld = long double;

const ll inf = (ll)1e18 + 100;

int n, m;
int d[100][100];
int s, b, k;

struct ship {
	int x, a, f, p;
} ss[100000];

struct base {
	int x, d, g;
} bb[100000];

struct maxflow {
	struct edge {
		int to, c, f;
	};

	vector<edge> e;
	vector<vi> g;
	int N, S, T;
	vi pt, d;
	int A;

	bool bfs() {
		fill_n(d.begin(), N, inf);
		d[S] = 0;
		queue<int> q;
		q.push(S);
		while (!q.empty()) {
			int v = q.front();
			q.pop();
			for (int i : g[v]) {
				edge& ee = e[i];
				if (ee.c - ee.f >= A && d[ee.to] == inf) {
					d[ee.to] = d[v] + 1;
					q.push(ee.to);
				}
			}

		}
		return (d[T] != inf);
	}

	int dfs(int v, int cmin) {
		if (v == T) {
			return cmin;
		}
		for (; pt[v] < sz(g[v]); pt[v]++) {
			int i = g[v][pt[v]];
			edge& ee = e[i];
			if (ee.c - ee.f >= A && d[ee.to] == d[v] + 1) {
				int f = dfs(ee.to, min(cmin, ee.c - ee.f));
				if (f > 0) {
					ee.f += f;
					e[i ^ 1].f -= f;
					return f;
				}
			}
		}
		return 0;
	}

	void dinic() {
		d.resize(N);
		pt.resize(N);
		int mf = 0;
		for (A = inf; A; A >>= 1) {
			while (bfs()) {
				fill_n(pt.begin(), N, 0);
				while (dfs(S, inf));
			}
		}
	}

	void addEdge(int u, int v, int c) {
		static int i = 0;
		e.pb({ v, c, 0 });
		e.pb({ u, 0, 0 });
		g[u].pb(i);
		g[v].pb(i ^ 1);
		i += 2;
		//cout << u << ' ' << v << endl;
	}

	void zhfs(int v, vector<bool>& was) {
		was[v] = true;
		for (int i : g[v]) {
			edge& ee = e[i];
			if (ee.c - ee.f > 0 && !was[ee.to]) {
				zhfs(ee.to, was);
			}
		}
	}
};

vi g1[100000];
vector<pii> e;
bool ban[100000];
int w[100000];

void dfs(int v) {
	ban[v] = true;
	for (int to : g1[v]) if(!ban[to]) dfs(to);
}

vector<pii> pl[100];
vi pm[100];

int32_t main() {
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	//ifstream cin("in.txt");
	cin >> n >> m;
	for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) if(i != j) d[i][j] = inf;
	for (int i = 0; i < m; i++) {
		int u, v; cin >> u >> v; --u; --v; d[u][v] = d[v][u] = 1;
	}
	for (int k = 0; k < n; k++) for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
	cin >> s >> b >> k;
	for (int i = 0; i < s; i++) cin >> ss[i].x >> ss[i].a >> ss[i].f >> ss[i].p, --ss[i].x;
	for (int i = 0; i < b; i++) cin >> bb[i].x >> bb[i].d >> bb[i].g, --bb[i].x, pl[bb[i].x].pb({ bb[i].d, bb[i].g });
	for (int i = 0; i < n; i++) {
		if (pl[i].empty()) continue;
		sort(all(pl[i]));
		pm[i].resize(sz(pl[i]));
		pm[i][0] = pl[i][0].second;
		for (int j = 1; j < sz(pm[i]); j++) {
			pm[i][j] = max(pm[i][j - 1], pl[i][j].second);
		}
	}
	vi broken;
	maxflow grape;
	grape.N = s + 2;
	grape.S = grape.N - 2;
	grape.T = grape.N - 1;
	grape.g.resize(grape.N);
	vi ord(s); iota(all(ord), 0);
	sort(all(ord), [](int i, int j) { return ss[i].a < ss[j].a; });
	vi pt(n, -1);
	for (int i : ord) {
		int hi = -1;
		//for (int p = 0; p < n; p++) if (ss[i].f >= d[ss[i].x][p]) for (pii bas : pl[p]) if (ss[i].a >= bas.first) hi = max(hi, bas.second);
		// me for (int p = 0; p < n; p++) if (ss[i].f >= d[ss[i].x][p]) for (int t = 0; t < sz(pl[p]) && ss[i].a >= pl[p][t].first; t++) hi = max(hi, pm[p][t]);
 		//for (int j = 0; j < b; j++) if (ss[i].a >= bb[j].d && ss[i].f >= d[ss[i].x][bb[j].x]) hi = max(hi, bb[j].g);
		for (int p = 0; p < n; p++) if(ss[i].f >= d[ss[i].x][p]) {
			while (pt[p] + 1 < sz(pl[p]) && ss[i].a >= pl[p][pt[p] + 1].first) pt[p]++;
			if (pt[p] != -1) hi = max(hi, pm[p][pt[p]]);
		}
		if (hi == -1) broken.pb(i);
		else {
			hi -= ss[i].p;
			w[i] = hi;
			//cout << i << ' ' << w[i] << endl;
		}
	}
	for (int i = 0; i < k; i++) {
		int u, v; cin >> u >> v; --u; --v;
		g1[v].pb(u); e.pb({ u, v });
	}
	for (int u : broken) if (!ban[u]) dfs(u);
	for (int i = 0; i < s; i++) if (!ban[i]) {
		//cout << '!' << i << endl;
		int hi = w[i];
		if (hi < 0) grape.addEdge(i, grape.T, -hi);
		else if (hi > 0) grape.addEdge(grape.S, i, hi);
	}
	for (pii r : e) {
		int u = r.first, v = r.second;
		if (!ban[u] && !ban[v]) grape.addEdge(u, v, inf);
	}
	grape.dinic();
	vector<bool> was(grape.N, false);
	grape.zhfs(grape.S, was);
	ll ans = 0;
	for (int u = 0; u < s; u++) {
		if (was[u]) {
			ans += w[u];
		}
	}
	cout << ans;
}

#include <bits/stdc++.h>

using namespace std;

const int inf = 1e9 + 7;
const long long infll = 1e18;

struct Edge {
  int from, to, index;
  long long cap, flow;
  Edge(int from, int to, long long cap, long long flow, int index) :
  from(from), to(to), index(index), cap(cap), flow(flow) {}
};

struct Dinic {
  int N;
  vector<vector<Edge> > G;
  vector<Edge *> dad;
  vector<int> Q;

  Dinic(int N) : N(N), G(N), dad(N), Q(N) {}

  void AddEdge(int from, int to, long long cap) {
    G[from].push_back(Edge(from, to, cap, 0LL, G[to].size()));
    if (from == to) G[from].back().index++;
    G[to].push_back(Edge(to, from, 0, 0, G[from].size() - 1));
  }

  long long BlockingFlow(int s, int t) {
    fill(dad.begin(), dad.end(), (Edge *) NULL);
    dad[s] = &G[0][0] - 1;

    int head = 0, tail = 0;
    Q[tail++] = s;
    while (head < tail) {
      int x = Q[head++];
      for (int i = 0; i < G[x].size(); i++) {
        Edge &e = G[x][i];
        if (!dad[e.to] && e.cap - e.flow > 0) {
          dad[e.to] = &G[x][i];
          Q[tail++] = e.to;
        }
      }
    }
    if (!dad[t]) return 0;

    long long totflow = 0;
    for (int i = 0; i < G[t].size(); i++) {
      Edge *start = &G[G[t][i].to][G[t][i].index];
      long long amt = infll;
      for (Edge *e = start; amt && e != dad[s]; e = dad[e->from]) {
        if (!e) { amt = 0; break; }
        amt = min(amt, e->cap - e->flow);
      }
      if (amt == 0) continue;
      for (Edge *e = start; amt && e != dad[s]; e = dad[e->from]) {
        e->flow += amt;
        G[e->to][e->index].flow -= amt;
      }
      totflow += amt;
    }
    return totflow;
  }

  long long GetMaxFlow(int s, int t) {
    long long totflow = 0;
    while (long long flow = BlockingFlow(s, t))
      totflow += flow;
    return totflow;
  }
};

const int N = 1e5 + 5;

int dist[111][111];
struct Ship {
  int x, a, f, p;
} ships[N];

int best[111];
int num[N];

int main() {
  int n, m;
  scanf("%d %d", &n, &m);
  for (int i = 1; i <= n; ++i) {
    for (int j = 1; j <= n; ++j)
      dist[i][j] = inf;
    dist[i][i] = 0;
  }
  for (int i = 0; i < m; ++i) {
    int u, v;
    scanf("%d %d", &u, &v);
    dist[u][v] = dist[v][u] = min(dist[u][v], 1);
  }
  for (int k = 1; k <= n; ++k)
    for (int i = 1; i <= n; ++i)
      for (int j = 1; j <= n; ++j)
        dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
  int s, b, k;
  scanf("%d %d %d", &s, &b, &k);
  vector<pair<int, int>> spaces(s);
  for (int i = 0; i < s; ++i) {
    int x, a, f, p;
    scanf("%d %d %d %d", &x, &a, &f, &p);
    ships[i] = {x, a, f, p};
    spaces[i] = make_pair(a, i);
  }
  vector<tuple<int, int, int>> bases(b);
  for (int i = 0; i < b; ++i) {
    int x, d, g;
    scanf("%d %d %d", &x, &d, &g);
    bases[i] = make_tuple(d, x, g);
  }
  sort(spaces.begin(), spaces.end());
  sort(bases.begin(), bases.end());
  memset(best, -1, sizeof best);
  for (int i = 0, j = 0; i < s; ++i) {
    int now = spaces[i].second;
    while (j < (int)bases.size() && get<0>(bases[j]) <= spaces[i].first) {
      int x, g;
      tie(ignore, x, g) = bases[j];
      ++j;
      best[x] = max(best[x], g);
    }
    int cur = -1;
    for (int j = 1; j <= n; ++j) {
      if (dist[ships[now].x][j] > ships[now].f) continue;
      cur = max(cur, best[j]);
    }
    if (cur < 0)
      ships[now].p = -inf;
    else
      ships[now].p = cur - ships[now].p;
  }
  vector<pair<int, int>> cons(k);
  vector<int> nodes;
  for (int i = 0; i < k; ++i) {
    int u, v;
    scanf("%d %d", &u, &v);
    --u, --v;
    cons[i] = make_pair(u, v);
    nodes.push_back(u);
    nodes.push_back(v);
  }
  sort(nodes.begin(), nodes.end());
  nodes.erase(unique(nodes.begin(), nodes.end()), nodes.end());
  Dinic mf((int)nodes.size() + 2);
  int st = nodes.size(), en = st + 1;
  long long tot = 0;
  for (int i = 0; i < s; ++i) {
    if (ships[i].p > 0) {
      tot += ships[i].p;
    }
    // cerr << ships[i].p << endl;
    int v = lower_bound(nodes.begin(), nodes.end(), i) - nodes.begin();
    if (v == (int)nodes.size() || nodes[v] != i)
      continue;
    if (ships[i].p > 0) {
      mf.AddEdge(st, v, ships[i].p);
    }
    else if (ships[i].p <= -inf) {
      mf.AddEdge(v, en, infll);
    }
    else {
      mf.AddEdge(v, en, -ships[i].p);
    }
  }
  for (auto it : cons) {
    int u = it.first, v = it.second;
    u = lower_bound(nodes.begin(), nodes.end(), u) - nodes.begin();
    v = lower_bound(nodes.begin(), nodes.end(), v) - nodes.begin();
    mf.AddEdge(u, v, inf);
  }
  tot -= mf.GetMaxFlow(st, en);
  printf("%lld\n", tot);
  return 0;
}

#include <bits/stdc++.h>

#define fast_cin() ios_base::sync_with_stdio(false); cin.tie(0);
#define pb push_back

using namespace std;

typedef long double ld;
typedef long long ll;
typedef long long LL;
typedef pair <int, int> pii;
typedef pair <ll, ll> pll;

struct Edge {
  int u, v;
  LL cap, flow;
  Edge() {}
  Edge(int u, int v, LL cap): u(u), v(v), cap(cap), flow(0) {}
};

struct Dinic {
  int N;
  vector<Edge> E;
  vector<vector<int>> g;
  vector<int> d, pt;

  Dinic(int N): N(N), E(0), g(N), d(N), pt(N) {}

  void AddEdge(int u, int v, LL cap) {
    if (u != v) {
      E.emplace_back(Edge(u, v, cap));
      g[u].emplace_back(E.size() - 1);
      E.emplace_back(Edge(v, u, 0));
      g[v].emplace_back(E.size() - 1);
    }
  }

  bool BFS(int S, int T) {
    queue<int> q({S});
    fill(d.begin(), d.end(), N + 1);
    d[S] = 0;
    while(!q.empty()) {
      int u = q.front(); q.pop();
      if (u == T) break;
      for (int k: g[u]) {
        Edge &e = E[k];
        if (e.flow < e.cap && d[e.v] > d[e.u] + 1) {
          d[e.v] = d[e.u] + 1;
          q.emplace(e.v);
        }
      }
    }
    return d[T] != N + 1;
  }

  LL DFS(int u, int T, LL flow = -1) {
    if (u == T || flow == 0) return flow;
    for (int &i = pt[u]; i < g[u].size(); ++i) {
      Edge &e = E[g[u][i]];
      Edge &oe = E[g[u][i]^1];
      if (d[e.v] == d[e.u] + 1) {
        LL amt = e.cap - e.flow;
        if (flow != -1 && amt > flow) amt = flow;
        if (LL pushed = DFS(e.v, T, amt)) {
          e.flow += pushed;
          oe.flow -= pushed;
          return pushed;
        }
      }
    }
    return 0;
  }

  LL MaxFlow(int S, int T) {
    LL total = 0;
    while (BFS(S, T)) {
      fill(pt.begin(), pt.end(), 0);
      while (LL flow = DFS(S, T))
        total += flow;
    }
    return total;
  }
};

struct ship_t {
	ll x, a, f, p;
};

struct base_t {
	ll x, d, g;
	bool operator<(const base_t &o) const {
		return d < o.d;
	}
};

const int N = 1e2 + 10, S = 1e5 + 10;
const ll inf = 1e12 + 42;

ship_t ship[S];
base_t base[S];
ll g[N][N];
vector<int> dep[S];
vector<pll> bases_at[N];
bool seen[S];
ll val[S];

int main()
{
	fast_cin();
	int n, m;
	cin >> n >> m;
	for (int i = 1; i <= n; ++i) {
		for (int j = i + 1; j <= n; ++j) {
			g[i][j] = g[j][i] = inf;
		}
	}
	for (int i = 0; i < m; ++i) {
		int u, v;
		cin >> u >> v;
		g[u][v] = g[v][u] = min(g[u][v], 1ll);
	}
	for (int k = 1; k <= n; ++k) {
		for (int i = 1; i <= n; ++i) {
			for (int j = 1; j <= n; ++j) {
				g[i][j] = min(g[i][j], g[i][k] + g[k][j]);
			}
		}
	}
	int s, b, k;
	cin >> s >> b >> k;
	for (int i = 1; i <= s; ++i) {
		cin >> ship[i].x >> ship[i].a >> ship[i].f >> ship[i].p;
	}
	for (int i = 1; i <= b; ++i) {
		cin >> base[i].x >> base[i].d >> base[i].g;
	}
	sort(base + 1, base + 1 + b);
	for (int i = 1; i <= b; ++i) {
		int p = base[i].x;
		if (bases_at[p].empty() or bases_at[p].back().second < base[i].g) {
			bases_at[p].pb({base[i].d, base[i].g});
		}
	}
	Dinic dinic(s + 2);
	int source = 0, sink = s + 1;
	ll ans = 0;
	for (int i = 1; i <= s; ++i) {
		bool found = false;
		for (int p = 1; p <= n; ++p) {
			if (g[ship[i].x][p] > ship[i].f) {
				continue;
			}
			auto it = upper_bound(bases_at[p].begin(), bases_at[p].end(), make_pair(ship[i].a, inf));
			if (it != bases_at[p].begin()) {
				--it;
				val[i] = max(val[i], it->second);
				found = true;
			}
		}
		val[i] -= ship[i].p;
		if (!found) {
			val[i] = -inf;
		}
		if (val[i] >= 0) {
			ans += val[i];
			dinic.AddEdge(source, i, val[i]);
		} else {
			dinic.AddEdge(i, sink, -val[i]);
		}
	}
	for (int i = 1; i <= k; ++i) {
		int u, v;
		cin >> u >> v;
		dep[u].pb(v);
		dinic.AddEdge(u, v, inf);
	}
	// for (int i = 1; i <= s; ++i) {
	// 	if (val[i] < 0) {
	// 		continue;
	// 	}
	// 	vector<int> vis = {i};
	// 	queue<int> q;
	// 	q.push(i);
	// 	seen[i] = true;
	// 	while (!q.empty()) {
	// 		int u = q.front();
	// 		q.pop();
	// 		if (val[u] < 0) {
	// 			dinic.AddEdge(i, u, inf);
	// 		}
	// 		for (auto &v : dep[u]) {
	// 			if (!seen[v]) {
	// 				seen[v] = true;
	// 				vis.pb(v);
	// 				q.push(v);
	// 			}
	// 		}
	// 	}
	// 	for (auto &u : vis) {
	// 		seen[u] = false;
	// 	}
	// }
	cout << ans - dinic.MaxFlow(source, sink);
}

#include <bits/stdc++.h>

#define fast_cin() ios_base::sync_with_stdio(false); cin.tie(0);
#define pb push_back

using namespace std;

typedef long double ld;
typedef long long ll;
typedef long long LL;
typedef pair <int, int> pii;
typedef pair <ll, ll> pll;

struct Edge {
  int u, v;
  LL cap, flow;
  Edge() {}
  Edge(int u, int v, LL cap): u(u), v(v), cap(cap), flow(0) {}
};

struct Dinic {
  int N;
  vector<Edge> E;
  vector<vector<int>> g;
  vector<int> d, pt;

  Dinic(int N): N(N), E(0), g(N), d(N), pt(N) {}

  void AddEdge(int u, int v, LL cap) {
    if (u != v) {
      E.emplace_back(Edge(u, v, cap));
      g[u].emplace_back(E.size() - 1);
      E.emplace_back(Edge(v, u, 0));
      g[v].emplace_back(E.size() - 1);
    }
  }

  bool BFS(int S, int T) {
    queue<int> q({S});
    fill(d.begin(), d.end(), N + 1);
    d[S] = 0;
    while(!q.empty()) {
      int u = q.front(); q.pop();
      if (u == T) break;
      for (int k: g[u]) {
        Edge &e = E[k];
        if (e.flow < e.cap && d[e.v] > d[e.u] + 1) {
          d[e.v] = d[e.u] + 1;
          q.emplace(e.v);
        }
      }
    }
    return d[T] != N + 1;
  }

  LL DFS(int u, int T, LL flow = -1) {
    if (u == T || flow == 0) return flow;
    for (int &i = pt[u]; i < g[u].size(); ++i) {
      Edge &e = E[g[u][i]];
      Edge &oe = E[g[u][i]^1];
      if (d[e.v] == d[e.u] + 1) {
        LL amt = e.cap - e.flow;
        if (flow != -1 && amt > flow) amt = flow;
        if (LL pushed = DFS(e.v, T, amt)) {
          e.flow += pushed;
          oe.flow -= pushed;
          return pushed;
        }
      }
    }
    return 0;
  }

  LL MaxFlow(int S, int T) {
    LL total = 0;
    while (BFS(S, T)) {
      fill(pt.begin(), pt.end(), 0);
      while (LL flow = DFS(S, T))
        total += flow;
    }
    return total;
  }
};

struct ship_t {
	ll x, a, f, p;
};

struct base_t {
	ll x, d, g;
	bool operator<(const base_t &o) const {
		return d < o.d;
	}
};

const int N = 1e2 + 10, S = 1e5 + 10;
const ll inf = 1e12 + 42;

ship_t ship[S];
base_t base[S];
ll g[N][N];
vector<int> dep[S];
vector<pll> bases_at[N];
bool seen[S];
ll val[S];

int main()
{
	fast_cin();
	int n, m;
	cin >> n >> m;
	for (int i = 1; i <= n; ++i) {
		for (int j = i + 1; j <= n; ++j) {
			g[i][j] = g[j][i] = inf;
		}
	}
	for (int i = 0; i < m; ++i) {
		int u, v;
		cin >> u >> v;
		g[u][v] = g[v][u] = min(g[u][v], 1ll);
	}
	for (int k = 1; k <= n; ++k) {
		for (int i = 1; i <= n; ++i) {
			for (int j = 1; j <= n; ++j) {
				g[i][j] = min(g[i][j], g[i][k] + g[k][j]);
			}
		}
	}
	int s, b, k;
	cin >> s >> b >> k;
	for (int i = 1; i <= s; ++i) {
		cin >> ship[i].x >> ship[i].a >> ship[i].f >> ship[i].p;
	}
	for (int i = 1; i <= b; ++i) {
		cin >> base[i].x >> base[i].d >> base[i].g;
	}
	sort(base + 1, base + 1 + b);
	for (int i = 1; i <= b; ++i) {
		int p = base[i].x;
		if (bases_at[p].empty() or bases_at[p].back().second < base[i].g) {
			bases_at[p].pb({base[i].d, base[i].g});
		}
	}
	Dinic dinic(s + 2);
	int source = 0, sink = s + 1;
	ll ans = 0;
	for (int i = 1; i <= s; ++i) {
		bool found = false;
		for (int p = 1; p <= n; ++p) {
			if (g[ship[i].x][p] > ship[i].f) {
				continue;
			}
			auto it = upper_bound(bases_at[p].begin(), bases_at[p].end(), make_pair(ship[i].a, inf));
			if (it != bases_at[p].begin()) {
				--it;
				val[i] = max(val[i], it->second);
				found = true;
			}
		}
		val[i] -= ship[i].p;
		if (!found) {
			val[i] = -inf;
		}
		if (val[i] >= 0) {
			ans += val[i];
			dinic.AddEdge(source, i, val[i]);
		} else {
			dinic.AddEdge(i, sink, -val[i]);
		}
	}
	for (int i = 1; i <= k; ++i) {
		int u, v;
		cin >> u >> v;
		dep[u].pb(v);
	}
	for (int i = 1; i <= s; ++i) {
		if (val[i] < 0) {
			continue;
		}
		vector<int> vis = {i};
		queue<int> q;
		q.push(i);
		seen[i] = true;
		while (!q.empty()) {
			int u = q.front();
			q.pop();
			if (val[u] < 0) {
				dinic.AddEdge(i, u, inf);
			}
			for (auto &v : dep[u]) {
				if (!seen[v]) {
					seen[v] = true;
					vis.pb(v);
					q.push(v);
				}
			}
		}
		for (auto &u : vis) {
			seen[u] = false;
		}
	}
	cout << ans - dinic.MaxFlow(source, sink);
}

#include <bits/stdc++.h>

using namespace std;

const int inf = 1e9 + 7;
const long long infll = 1e18;

struct Edge {
  int from, to, index;
  long long cap, flow;
  Edge(int from, int to, long long cap, long long flow, int index) :
  from(from), to(to), index(index), cap(cap), flow(flow) {}
};

struct Dinic {
  int N;
  vector<vector<Edge> > G;
  vector<Edge *> dad;
  vector<int> Q;

  Dinic(int N) : N(N), G(N), dad(N), Q(N) {}

  void AddEdge(int from, int to, long long cap) {
    G[from].push_back(Edge(from, to, cap, 0LL, G[to].size()));
    if (from == to) G[from].back().index++;
    G[to].push_back(Edge(to, from, 0, 0, G[from].size() - 1));
  }

  long long BlockingFlow(int s, int t) {
    fill(dad.begin(), dad.end(), (Edge *) NULL);
    dad[s] = &G[0][0] - 1;

    int head = 0, tail = 0;
    Q[tail++] = s;
    while (head < tail) {
      int x = Q[head++];
      for (int i = 0; i < G[x].size(); i++) {
        Edge &e = G[x][i];
        if (!dad[e.to] && e.cap - e.flow > 0) {
          dad[e.to] = &G[x][i];
          Q[tail++] = e.to;
        }
      }
    }
    if (!dad[t]) return 0;

    long long totflow = 0;
    for (int i = 0; i < G[t].size(); i++) {
      Edge *start = &G[G[t][i].to][G[t][i].index];
      long long amt = infll;
      for (Edge *e = start; amt && e != dad[s]; e = dad[e->from]) {
        if (!e) { amt = 0; break; }
        amt = min(amt, e->cap - e->flow);
      }
      if (amt == 0) continue;
      for (Edge *e = start; amt && e != dad[s]; e = dad[e->from]) {
        e->flow += amt;
        G[e->to][e->index].flow -= amt;
      }
      totflow += amt;
    }
    return totflow;
  }

  long long GetMaxFlow(int s, int t) {
    long long totflow = 0;
    while (long long flow = BlockingFlow(s, t))
      totflow += flow;
    return totflow;
  }
};

const int N = 1e5 + 5;

int dist[111][111];
struct Ship {
  int x, a, f, p;
} ships[N];

int best[111];
int num[N];

int main() {
  int n, m;
  scanf("%d %d", &n, &m);
  for (int i = 1; i <= n; ++i) {
    for (int j = 1; j <= n; ++j)
      dist[i][j] = inf;
    dist[i][i] = 0;
  }
  for (int i = 0; i < m; ++i) {
    int u, v;
    scanf("%d %d", &u, &v);
    dist[u][v] = dist[v][u] = min(dist[u][v], 1);
  }
  for (int k = 1; k <= n; ++k)
    for (int i = 1; i <= n; ++i)
      for (int j = 1; j <= n; ++j)
        dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
  int s, b, k;
  scanf("%d %d %d", &s, &b, &k);
  vector<pair<int, int>> spaces(s);
  for (int i = 0; i < s; ++i) {
    int x, a, f, p;
    scanf("%d %d %d %d", &x, &a, &f, &p);
    ships[i] = {x, a, f, p};
    spaces[i] = make_pair(a, i);
  }
  vector<tuple<int, int, int>> bases(b);
  for (int i = 0; i < b; ++i) {
    int x, d, g;
    scanf("%d %d %d", &x, &d, &g);
    bases[i] = make_tuple(d, x, g);
  }
  sort(spaces.begin(), spaces.end());
  sort(bases.begin(), bases.end());
  memset(best, -1, sizeof best);
  for (int i = 0, j = 0; i < s; ++i) {
    int now = spaces[i].second;
    while (j < (int)bases.size() && get<0>(bases[j]) <= spaces[i].first) {
      int x, g;
      tie(ignore, x, g) = bases[j];
      ++j;
      best[x] = max(best[x], g);
    }
    int cur = -1;
    for (int j = 1; j <= n; ++j) {
      if (dist[ships[now].x][j] > ships[now].f) continue;
      cur = max(cur, best[j]);
    }
    if (cur < 0)
      ships[now].p = -inf;
    else
      ships[now].p = cur - ships[now].p;
  }
  vector<pair<int, int>> cons(k);
  vector<int> nodes;
  for (int i = 0; i < k; ++i) {
    int u, v;
    scanf("%d %d", &u, &v);
    --u, --v;
    cons[i] = make_pair(u, v);
    nodes.push_back(u);
    nodes.push_back(v);
  }
  sort(nodes.begin(), nodes.end());
  nodes.erase(unique(nodes.begin(), nodes.end()), nodes.end());
  Dinic mf((int)nodes.size() + 2);
  int st = nodes.size(), en = st + 1;
  long long tot = 0;
  for (int i = 0; i < s; ++i) {
    if (ships[i].p > 0) {
      tot += ships[i].p;
    }
    // cerr << ships[i].p << endl;
    int v = lower_bound(nodes.begin(), nodes.end(), i) - nodes.begin();
    if (v == (int)nodes.size() || nodes[v] != i)
      continue;
    if (ships[i].p > 0) {
      mf.AddEdge(st, v, ships[i].p);
    }
    else if (ships[i].p < -inf) {
      mf.AddEdge(v, en, infll);
    }
    else {
      mf.AddEdge(v, en, -ships[i].p);
    }
  }
  for (auto it : cons) {
    int u = it.first, v = it.second;
    u = lower_bound(nodes.begin(), nodes.end(), u) - nodes.begin();
    v = lower_bound(nodes.begin(), nodes.end(), v) - nodes.begin();
    mf.AddEdge(u, v, inf);
  }
  tot -= mf.GetMaxFlow(st, en);
  printf("%lld\n", tot);
  return 0;
}

#include <bits/stdc++.h>
#define fst first
#define snd second
#define fore(i,a,b) for(int i=a,ThxDem=b;i<ThxDem;++i)
#define pb push_back
#define ALL(s) s.begin(),s.end()
#define FIN ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define SZ(s) int(s.size())
using namespace std;
typedef long long ll;
typedef pair<ll,ll> ii;

ll d[110][110],INF=1e18;
ll v[100010];
vector<ii> base[110];
vector<ll> bst[110];

// Min cut: nodes with dist>=0 vs nodes with dist<0
// Matching MVC: left nodes with dist<0 + right nodes with dist>0
struct Dinic{
	int nodes,src,dst;
	vector<int> dist,q,work;
	struct edge {int to,rev;ll f,cap;};
	vector<vector<edge>> g;
	Dinic(int x):nodes(x),g(x),dist(x),q(x),work(x){}
	void add_edge(int s, int t, ll cap){
		g[s].pb((edge){t,SZ(g[t]),0,cap});
		g[t].pb((edge){s,SZ(g[s])-1,0,0});
	}
	bool dinic_bfs(){
		fill(ALL(dist),-1);dist[src]=0;
		int qt=0;q[qt++]=src;
		for(int qh=0;qh<qt;qh++){
			int u=q[qh];
			fore(i,0,SZ(g[u])){
				edge &e=g[u][i];int v=g[u][i].to;
				if(dist[v]<0&&e.f<e.cap)dist[v]=dist[u]+1,q[qt++]=v;
			}
		}
		return dist[dst]>=0;
	}
	ll dinic_dfs(int u, ll f){
		if(u==dst)return f;
		for(int &i=work[u];i<SZ(g[u]);i++){
			edge &e=g[u][i];
			if(e.cap<=e.f)continue;
			int v=e.to;
			if(dist[v]==dist[u]+1){
				ll df=dinic_dfs(v,min(f,e.cap-e.f));
				if(df>0){e.f+=df;g[v][e.rev].f-=df;return df;}
			}
		}
		return 0;
	}
	ll max_flow(int _src, int _dst){
		src=_src;dst=_dst;
		ll result=0;
		while(dinic_bfs()){
			fill(ALL(work),0);
			while(ll delta=dinic_dfs(src,INF))result+=delta;
		}
		return result;
	}
};

int main(){FIN;
	int n,m; cin>>n>>m;
	fore(i,0,n) fore(j,0,n) d[i][j]=INF*(i!=j);
	fore(i,0,m){
		int x,y; cin>>x>>y; d[x-1][y-1]=d[y-1][x-1]=1;
	}
	fore(k,0,n) fore(i,0,n) fore(j,0,n){
		if(d[i][k]!=INF&&d[k][j]!=INF) d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
	}
	ll ans=0,s,b,k; cin>>s>>b>>k;
	fore(i,0,s) v[i]=-INF;
	vector<pair<ii,ii>> a(s);
	fore(i,0,s) cin>>a[i].fst.fst>>a[i].fst.snd>>a[i].snd.fst>>a[i].snd.snd,a[i].fst.fst--;
	fore(i,0,b){
		ll x,di,g; cin>>x>>di>>g; x--; base[x].pb({di,g});
	}
	fore(i,0,n){
		sort(ALL(base[i])); bst[i].resize(SZ(base[i]));
		fore(j,0,SZ(base[i])){
			bst[i][j]=base[i][j].snd;
			if(j) bst[i][j]=max(bst[i][j],bst[i][j-1]);
		}
	}
	Dinic nt(s+2);
	fore(i,0,SZ(a)){
		fore(j,0,n){
			int top=upper_bound(ALL(base[j]),(ii){a[i].fst.snd,INF})-base[j].begin()-1;
			if(d[a[i].fst.fst][j]<=a[i].snd.fst&&top>=0){
				v[i]=max(v[i],bst[j][top]-a[i].snd.snd);
			}
		}
		if(v[i]<0) nt.add_edge(i+1,s+1,-v[i]);
		else ans+=v[i], nt.add_edge(0,i+1,v[i]);
	}
	fore(i,0,k){
		int x,y; cin>>x>>y; nt.add_edge(x,y,INF);
	}
	cout << ans-nt.max_flow(0,s+1)<<"\n";
}

#include <bits/stdc++.h>
using namespace std;

using ll=long long;
#define int ll

#define rng(i,a,b) for(int i=int(a);i<int(b);i++)
#define rep(i,b) rng(i,0,b)
#define gnr(i,a,b) for(int i=int(b)-1;i>=a;i--)
#define per(i,b) gnr(i,0,b)
#define pb push_back
#define eb emplace_back
#define a first
#define b second
#define bg begin()
#define ed end()
#define all(x) x.bg,x.ed
#ifdef LOCAL
#define dmp(x) cerr<<__LINE__<<" "<<#x<<" "<<x<<endl
#else
#define dmp(x) void(0)
#endif

template<class t,class u> void chmax(t&a,u b){if(a<b)a=b;}
template<class t,class u> void chmin(t&a,u b){if(b<a)a=b;}

template<class t> using vc=vector<t>;
template<class t> using vvc=vc<vc<t>>;

using pi=pair<int,int>;
using vi=vc<int>;

template<class t,class u>
ostream& operator<<(ostream& os,const pair<t,u>& p){
	return os<<"{"<<p.a<<","<<p.b<<"}";
}

template<class t> ostream& operator<<(ostream& os,const vc<t>& v){
	os<<"{";
	for(auto e:v)os<<e<<",";
	return os<<"}";
}

const int inf=LLONG_MAX/3;

template<class d>
struct maxflow{
	struct E{
		int to,rev;
		d cap;
	};
	vvc<E> g;
	vi itr,lv;
	maxflow(int n):g(n),itr(n),lv(n){}
	void ae(int s,int t,d c){
		g[s].pb({t,(int)g[t].size(),c});
		g[t].pb({s,(int)g[s].size()-1,0});
	}
	void bfs(int s){
		fill(all(lv),-1);
		lv[s]=0;
		queue<int> q;
		q.push(s);
		while(q.size()){
			int v=q.front();q.pop();
			for(auto e:g[v])if(e.cap>0&&lv[e.to]==-1){
				lv[e.to]=lv[v]+1;
				q.push(e.to);
			}
		}
	}
	d dfs(int v,int t,d f){
		if(v==t)return f;
		d res=0;
		for(int&i=itr[v];i<(int)g[v].size();i++){
			E& e=g[v][i];
			if(e.cap>0&&lv[e.to]==lv[v]+1){
				d a=dfs(e.to,t,min(f,e.cap));
				if(a>0){
					e.cap-=a;
					g[e.to][e.rev].cap+=a;
					res+=a;
					f-=a;
					if(f<=0)break;
				}
			}
		}
		return res;
	}
	d calc(int s,int t){
		d f=0;
		while(1){
			bfs(s);
			if(lv[t]==-1)
				return f;
			fill(all(itr),0);
			f+=dfs(s,t,1e9);
		}
	}
};

void sub(vi pro,int k){
	int n=pro.size();
	vi iso(n,1);
	vc<pi> es;
	rep(_,k){
		int a,b;cin>>a>>b;
		a--;b--;
		es.eb(a,b);
		iso[a]=0;
		iso[b]=0;
	}
	int base=0;
	vi idx;
	rep(i,n)if(iso[i]){
		base+=max(int(0),pro[i]);
	}else{
		idx.pb(i);
	}

	int s=idx.size();
	maxflow<int> mcf(1+s+1);
	rep(i,s){
		if(pro[idx[i]]>0){
			base+=pro[idx[i]];
			mcf.ae(0,1+i,pro[idx[i]]);
		}else{
			mcf.ae(1+i,1+s,-pro[idx[i]]);
		}
	}
	for(auto e:es){
		int a=lower_bound(all(idx),e.a)-idx.bg;
		int b=lower_bound(all(idx),e.b)-idx.bg;
		mcf.ae(1+a,1+b,inf);
	}

	cout<<base-mcf.calc(0,1+s)<<endl;
}

signed main(){
	cin.tie(0);
	ios::sync_with_stdio(0);
	cout<<fixed<<setprecision(20);

	int n,m;cin>>n>>m;
	vvc<int> dist(n,vi(n,inf));
	rep(i,n)dist[i][i]=0;
	rep(_,m){
		int a,b;cin>>a>>b;
		a--;b--;
		dist[a][b]=1;
		dist[b][a]=1;
	}
	rep(k,n)rep(i,n)rep(j,n)
		chmin(dist[i][j],dist[i][k]+dist[k][j]);

	int s,b,k;cin>>s>>b>>k;
	vc<tuple<int,int,int,int>> xafp;
	rep(i,s){
		int x,a,f,p;cin>>x>>a>>f>>p;
		x--;
		xafp.eb(x,a,f,p);
	}
	vc<tuple<int,int,int>> xdg;
	rep(i,b){
		int x,d,g;cin>>x>>d>>g;
		x--;
		xdg.eb(x,d,g);
	}
	vc<pi> ord;
	rep(i,s)
		ord.eb(get<1>(xafp[i]),b+i);
	rep(i,b)
		ord.eb(get<1>(xdg[i]),i);
	vi pro(s);
	vi mxg(n,-inf);
	sort(all(ord));
	for(auto kv:ord){
		int i=kv.b;
		if(i<b){
			chmax(mxg[get<0>(xdg[i])],get<2>(xdg[i]));
		}else{
			i-=b;
			int x,a,f,p;
			tie(x,a,f,p)=xafp[i];
			int mx=-inf;
			rep(j,n)if(dist[x][j]<=f)
				chmax(mx,mxg[j]);
			pro[i]=mx-p;
		}
	}
	sub(pro,k);
}

#pragma GCC optimize(3)
#pragma GCC optimize(2)
#include <bits/stdc++.h>
#define MAX_SIZE 3011
typedef long long ll;
#define INF 1000000000000000
using namespace std;

struct Maxflow {
    struct edge {
    	int from, to;
    	ll flow, capacity;
    };

    // start and end point
    int s, t;

    // list array
    vector<edge> edg;

    // g reference to the ith vertex's edges
    vector<int> g[MAX_SIZE];

    // distance array and visited array
    int dist[MAX_SIZE], visited[MAX_SIZE];
    int cur[MAX_SIZE];

    void init() {
    	edg.clear();
    	int i;
    	for (i = 0 ; i < MAX_SIZE; i++) {
    		g[i].clear();
    	}
    }

    void addedge(int from, int to, ll capacity) {
    	edge e1 = edge{from, to, 0ll, capacity};
    	edge e2 = edge{to, from, 0ll, 0ll};
    	edg.push_back(e1), edg.push_back(e2);
    	g[from].push_back((int) edg.size() - 2);
    	g[to].push_back((int) edg.size() - 1);
    }

    // construct the level graph
    bool bfs() {
    	memset(visited,0,sizeof(visited));
    	memset(dist,0,sizeof(dist));
    	queue<int> q;
    	q.push(s);
    	visited[s] = 1;
    	dist[s] = 0;
    	while (!q.empty()) {
    		int v = q.front();
    		q.pop();
    		for (int i = 0 ; i < (int) g[v].size(); i++) {
    			edge &e = edg[g[v][i]];
    			int nxt = e.to;
    			if (!visited[nxt] && e.capacity > e.flow) {
    				dist[nxt] = dist[v] + 1;
    				q.push(nxt);
    				visited[nxt] = 1;
    			}
    		}
    	}

    	return visited[t];
    }

    ll dfs(int x, ll cp) {
    	if (x == t || cp == 0) {
    		return cp;
    	}

    	ll flow = 0, newflow;
    	for (int &y = cur[x]; y < (int) g[x].size(); y++) {
    		edge &e = edg[g[x][y]];
    		if (dist[x] + 1 == dist[e.to]) {
    			ll minn = min(cp, e.capacity - e.flow);
    			newflow = dfs(e.to, minn);
    			if (newflow > 0) {
    				e.flow += newflow;
    				edg[g[x][y] ^1].flow -= newflow;
    				flow += newflow;
    				cp -= newflow;

    				if (cp == 0) {
    					break;
    				}
    			}
    		}
    	}

    	return flow;
    }

    ll Dinic(){
        ll flow=0;
        while(bfs()){
            memset(cur,0,sizeof(cur));
            flow += dfs(s,INF);
        }
        return flow;
    }
};

Maxflow mf;
ll dist[111][111];
int n, m;

struct spa {
    int id, x, a, f, p;
    bool operator < (spa other) const {
        return a < other.a;
    }
};

struct base {
    int d, g;
    bool operator < (base other) const {
        return d < other.d;
    }
};

// G[i] stores all the base at node i
vector<base> G[111];
spa sp[100011];
ll profit[100011];
pair<int, int> relation[MAX_SIZE];
int special[100011];
vector<int> disc;

int main() {
    int i, j, k, S, B;
    mf.s = MAX_SIZE - 2, mf.t = MAX_SIZE - 1;
    scanf("%d%d", &n, &m);
    for (i = 1; i <= n; ++i) {
        for (j = 1; j <= n; ++j) {
            if (i != j) {
                dist[i][j] = INF;
            }
        }
    }

    for (i = 0 ; i < 100011; ++i) profit[i] = -INF;

    for (i = 1; i <= m; ++i) {
        int v1, v2;
        scanf("%d%d", &v1, &v2);
        dist[v1][v2] = dist[v2][v1] = min(dist[v1][v2], 1ll);
    }

    for (k = 1; k <= n; ++k) {
        for (i = 1; i <= n; ++i) {
            for (j = 1; j <= n; ++j) {
                dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
            }
        }
    }

    scanf("%d%d%d", &S, &B, &m);
    for (i = 1; i <= S; ++i) {
        scanf("%d%d%d%d", &sp[i].x, &sp[i].a, &sp[i].f, &sp[i].p);
        sp[i].id = i;
    }

    for (i = 1; i <= B; ++i) {
        int v, d, g;
        scanf("%d%d%d", &v, &d, &g);
        G[v].push_back(base{d, g});
    }

    sort(sp + 1, sp + 1 + S);
    for (i = 1; i <= n; ++i) {
        sort(G[i].begin(), G[i].end());
        ll gold = -INF;
        int sz = G[i].size();
        for (k = 1, j = 0; k <= S; ++k) {
            while (j < sz && sp[k].a >= G[i][j].d) {
                gold = max(gold, (ll) G[i][j].g);
                ++j;
            }

            if (sp[k].f >= dist[i][sp[k].x]) {
                profit[sp[k].id] = max(profit[sp[k].id],  gold - sp[k].p);
            }
        }
    }

    ll ans = 0, tol = 0;
    for (i = 1; i <= m; ++i) {
        scanf("%d%d", &relation[i].first, &relation[i].second);
        special[relation[i].first] = special[relation[i].second] = 1;
    }

    for (i = 1; i <= S; ++i) {
        if (!special[i] && profit[i] > 0) {
            ans += profit[i];
        }

        if (special[i]) {
            disc.push_back(i);
        }
    }

    for (i = 0 ; i < (int) disc.size(); ++i) {
        if (profit[disc[i]] < 0) {
            mf.addedge(i, mf.t, -profit[disc[i]]);
        } else {
            mf.addedge(mf.s, i, profit[disc[i]]);
            tol += profit[disc[i]];
        }
    }
/*
    for (i = 1; i <= S; ++i) {
        cout << profit[i] << " ";
    }

    cout << endl;
*/
    for (i = 1; i <= m; ++i) {
        if (binary_search(disc.begin(), disc.end(), relation[i].first)
         && binary_search(disc.begin(), disc.end(), relation[i].second)) {
            int id1 = lower_bound(disc.begin(), disc.end(), relation[i].first) - disc.begin();
            int id2 = lower_bound(disc.begin(), disc.end(), relation[i].second) - disc.begin();
            mf.addedge(id1, id2, INF);
        }
    }

    ans = ans + tol - mf.Dinic();

    cout << ans << endl;
    return 0;
}

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <vector>
#include <set>
#include <map>
#include <unordered_set>
#include <unordered_map>
#include <queue>
#include <ctime>
#include <cassert>
#include <complex>
#include <string>
#include <cstring>
#include <chrono>
#include <random>
#include <queue>
#include <bitset>
using namespace std;

#ifdef LOCAL
	#define eprintf(...) fprintf(stderr, __VA_ARGS__)
#else
	#define eprintf(...) 42
#endif

typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, int> pli;
typedef pair<ll, ll> pll;
typedef long double ld;
#define mp make_pair
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

const ll INF = (ll)1e18 + 33;
const int V = 101;
const int N = 100010;
int G[V][V];
int n;
int m, k;
int a[N][4];
ll c[N];
vector<pii> b[N];

struct Edge {
	int v, to;
	ll cap;

	Edge() : v(), to(), cap() {}
	Edge (int _v, int _to, ll _cap) : v(_v), to(_to), cap(_cap) {}
};
Edge ed[N];
int edSz;
vector<int> g[N];
int dist[N];
int q[N];
int topQ;
int idx[N];
int idd[N];
int S, T;

void addEdge(int v, int to, ll cap) {
	ed[edSz] = Edge(v, to, cap);
	g[v].push_back(edSz++);
	ed[edSz] = Edge(to, v, 0);
	g[to].push_back(edSz++);
}

bool BFS() {
	for (int i = 0; i <= T; i++)
		dist[i] = N;
	topQ = 0;
	dist[S] = 0;
	q[topQ++] = S;
	for (int i = 0; i < topQ; i++) {
		int v = q[i];
		for (int id : g[v]) {
			Edge e = ed[id];
			if (e.cap <= 0) continue;
			int to = e.to;
			if (dist[to] <= dist[v] + 1) continue;
			dist[to] = dist[v] + 1;
			q[topQ++] = to;
		}
	}
	return dist[T] < N;
}
ll dfs(int v, ll flow) {
	if (v == T || flow == 0) return flow;
	ll res = 0;
	for (int &i = idx[v]; i < (int)g[v].size(); i++) {
		int id = g[v][i];
		Edge e = ed[id];
		int to = e.to;
		if (dist[to] != dist[v] + 1) continue;
		ll df = dfs(to, min(flow, e.cap));
		res += df;
		flow -= df;
		ed[id].cap -= df;
		ed[id ^ 1].cap += df;
		if (flow == 0) return res;
	}
	return res;
}

ll Flow() {
	ll res = 0;
	while(BFS()) {
		for (int i = 0; i <= T; i++)
			idx[i] = 0;
		res += dfs(S, INF);
	}
	return res;
}

void readGraph() {
	int e;
	scanf("%d%d", &n, &e);
	for (int i = 0; i < n; i++)
		for (int j = 0; j < n; j++)
			G[i][j] = (i == j ? 0 : N);
	while(e--) {
		int v, u;
		scanf("%d%d", &v, &u);
		v--;u--;
		if (v != u)
			G[v][u] = G[u][v] = 1;
	}
	for (int z = 0; z < n; z++)
		for (int x = 0; x < n; x++)
			for (int y = 0; y < n; y++)
				G[x][y] = min(G[x][y], G[x][z] + G[z][y]);
}

ll read() {
	readGraph();
	scanf("%d%d%d", &n, &k, &m);
	for (int i = 0; i < n; i++) {
		scanf("%d%d%d%d", &a[i][0], &a[i][1], &a[i][2], &a[i][3]);
		a[i][0]--;
	}
	for (int i = 0; i < k; i++) {
		int v, x, y;
		scanf("%d%d%d", &v, &x, &y);
		v--;
		b[v].push_back(mp(x, y));
	}
	for (int v = 0; v < V; v++) {
		sort(b[v].begin(), b[v].end());
		for (int i = 1; i < (int)b[v].size(); i++)
			b[v][i].second = max(b[v][i].second, b[v][i - 1].second);
	}
	for (int i = 0; i < n; i++) {
		c[i] = -INF;
		for (int v = 0; v < V; v++) {
			if (b[v].empty()) continue;
			if (G[a[i][0]][v] > a[i][2]) continue;
			int p = upper_bound(b[v].begin(), b[v].end(), mp(a[i][1] + 1, -1)) - b[v].begin();
			if (p > 0) c[i] = max(c[i], (ll)b[v][p - 1].second);
		}
		c[i] -= a[i][3];
	}
	S = 0;
	for (int i = 0; i < n; i++)
		idd[i] = -1;
	for (int i = 0; i < m; i++) {
		int v, u;
		scanf("%d%d", &v, &u);
		v--;u--;
		if (idd[v] == -1) idd[v] = S++;
		if (idd[u] == -1) idd[u] = S++;
		v = idd[v];
		u = idd[u];
		addEdge(v, u, INF);
	}
	T = S + 1;
	ll ans = 0;
	for (int v = 0; v < n; v++) {
		if (idd[v] == -1) {
			ans += max(0LL, c[v]);
			continue;
		}
		if (c[v] <= 0) {
			addEdge(idd[v], T, -c[v]);
		} else {
			ans += c[v];
			addEdge(S, idd[v], c[v]);
		}
	}
	return ans;
}

int main()
{
//	freopen("input.txt", "r", stdin);
//	freopen("output.txt", "w", stdout);

	ll ans = read();
	printf("%lld\n", ans - Flow());

	return 0;
}

/*
    Author : manu_sy
*/
#include "bits/stdc++.h"
using namespace std;

/** Template Begins **/
#define int ll
typedef long long        ll;
typedef pair<int,int>    PII;

#define IOS         ios_base::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
#define endl        '\n'
#define pb          push_back
#define F           first
#define S           second
#define mp          make_pair
#define all(a)      (a).begin(), (a).end()
#define FOR(i,a,b)  for(int i=a;i<=b;i++)
#define LP(i,n)     for(int i=0;i< n;i++)

/* Debug */

template<class L, class R> ostream &operator<<(ostream &os, pair<L,R> P) {
  return os << "(" << P.F << "," << P.S << ")";
}

template<class T> ostream &operator<<(ostream& os, vector<T> V) {
  os << "["; for (auto vv : V) os << vv << ","; return os << "]";
}

template<class TH> void _dbg(const char *sdbg, TH h){ cerr << sdbg << '=' << h << endl; }

template<class TH, class... TA> void _dbg(const char *sdbg, TH h, TA... a) {
  while(*sdbg!=',') cerr << *sdbg++;
  cerr<<'='<<h<<','; _dbg(sdbg+1, a...);
}

#ifdef LOCALI
#define debug(...) _dbg(#__VA_ARGS__, __VA_ARGS__)
#else
#define debug(...) (__VA_ARGS__)
#define cerr if(0)cout
#endif

/* Debug Ends */

const int NN = 1e2+7, N = 1e5+7, NNN = 2e3+7;
const int INF1 = 1e17+100;

/** Template Ends **/

int n, m, dist[NN][NN], s, b, k;
bool mark[N];
int sx[N], sa[N], sf[N], sp[N];
vector<PII> base[NN];
int profit[N];
vector<int> posp, negp;
int d1[N], d2[N], aa, bb;
ll ans;

void fill_graph()
{
    FOR(i,1,n) FOR(j,1,n) dist[i][j] = (i == j ? 0 : INF1);
    LP(i,m)
    {
        int u, v; cin >> u >> v;
        dist[u][v] = dist[v][u] = min(dist[u][v], 1LL);
    }
    FOR(k,1,n) FOR(i,1,n) FOR(j,1,n) dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
}
void simplify_bases()
{
    FOR(i,1,n) sort(all(base[i]));
    FOR(i,1,n)
    {
        int mg = 0;
        for (auto &bs: base[i]) bs.S = max(bs.S, mg), mg = bs.S;
        debug(i, base[i]);
    }
}
void calc_profit()
{
    FOR(i,1,s)
    {
        profit[i] = -INF1;
        FOR(j,1,n) if (dist[sx[i]][j] <= sf[i])
        {
            int pos = upper_bound(all(base[j]), mp(sa[i], INF1)) - base[j].begin() - 1;
            if (pos == -1)  continue;
            profit[i] = max(profit[i], base[j][pos].S - sp[i]);
        }
        debug(i, profit[i]);
    }
}
void get_dep()
{
    LP(i,k)
    {
        debug(d1[i], d2[i]);
        cin >> d1[i] >> d2[i];
        mark[d1[i]] = mark[d2[i]] = true;
    }
    FOR(i,1,s)
    {
        ans += max(0LL, profit[i]);
        if (!mark[i]) continue;
        if (profit[i] >= 0) posp.pb(i);
        else                negp.pb(i);
    }
    sort(all(posp));   sort(all(negp));
    debug(posp); debug(negp);
}
namespace Maxflow{
    const int maxn=2022;
    const int maxm=66666;
    const int inf=INF1;

    int g[maxn],to[maxm],np[maxm],cp;
    int n,u,v,now,source,sink;
    int sum,cap[maxm],a[maxn];
    int d[maxn],p[maxn],cur[maxn],cnt[maxn];

    void add_edge(int x,int y,int z){
        // printf("%d - %d: %d\n",x,y,z);
        cap[cp]=z;to[cp]=y;np[cp]=g[x];g[x]=cp++;cap[cp]=0;to[cp]=x;np[cp]=g[y];g[y]=cp++;
    }

    void init(){
        cp=2; memset(g,0,sizeof(g));
    }
    int maxflow(){
        sum=0;
        for(u=1;u<=n;u++)cur[u]=g[u]; a[u=source]=inf; memset(d,0,sizeof(int)*(n+1)); memset(cnt,0,sizeof(int)*(n+1)); cnt[0]=n;
        while(d[source]<n)
        {
            for(now=cur[u];now;now=np[now])if(cap[now]&&d[v=to[now]]+1==d[u])break; cur[u]=now;
            if(now)
            {
                p[v]=now; a[v]=cap[now]; if(a[v]>a[u])a[v]=a[u];
                if((u=v)==sink)
                {
                    do{cap[p[u]]-=a[sink]; cap[p[u]^1]+=a[sink]; u=to[p[u]^1];}while(u!=source);
                    sum+=a[sink]; a[source]=inf;
                }
            }
            else
            {
                if(--cnt[d[u]]==0)break; d[u]=n; cur[u]=g[u];
                for(now=g[u];now;now=np[now]) if(cap[now] && d[u]>d[to[now]]+1) d[u]=d[to[now]]+1;
                cnt[d[u]]++;
                if(u!=source)u=to[p[u]^1];
            }
        }
    //    printf("maxflow\n");
        return sum;
    }
}
int findp(int s1) {
    if (profit[s1] >= 0)    return lower_bound(all(posp), s1) - posp.begin() + 1;
    else                    return lower_bound(all(negp), s1) - negp.begin() + aa + 1;
}
signed main() {

    IOS;
    cin >> n >> m;
    fill_graph();
    cin >> s >> b >> k;
    FOR(i,1,s) cin >> sx[i] >> sa[i] >> sf[i] >> sp[i];
    LP(i,b)
    {
        int x, d, g;    cin >> x >> d >> g;
        base[x].pb(mp(d, g));
    }
    simplify_bases();
    calc_profit();
    get_dep();
    aa = posp.size(), bb = negp.size();

    Maxflow::init();
    Maxflow::n = aa + bb + 2;
    Maxflow::source = 0, Maxflow::sink = aa + bb + 1;
    LP(i,aa) Maxflow::add_edge(0, i + 1, profit[posp[i]]);
    LP(i,bb) Maxflow::add_edge(aa + i + 1, Maxflow::sink, -profit[negp[i]]);

    LP(i,k)
    {
        int s1 = d1[i], s2 = d2[i];
        int x1 = findp(s1), x2 = findp(s2);
        debug(s1, s2, x1, x2);
        Maxflow::add_edge(x1, x2, INF1);
    }
    int ff = Maxflow::maxflow();
    debug(ff);
    cout << ans - ff << endl;

    return 0;
}

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;

struct brod {
	int x, a, p, i;
	ll f;
};

struct baza {
	int x, d,    g;
};

int d[105][105];
int n, m;

struct dependency {
	int u, v;
};

brod a[100005];
baza c[100005];

vector<pair<int, ll>> zlato[105];
int zlato_ptr[105];

dependency dep[1005];
int ugly[100005];
// drugi graf za analizu (scc)
ll p2[2005]; int s2;
basic_string<int> df[2005];
bool reach[2005][2005];

void dfs2(int x, bool* reach) {
	reach[x] = true;
	for (int y : df[x]) {
		if (!reach[y]) {
			dfs2(y, reach);
		}
	}
}
// treci graf
int s3;
int c3[2005];
ll p3[2005];
basic_string<int> e3[2005];

// cetvrti graf
const ll LINF = 1'000'000'000'000'000'000ll;
struct maxflow {
	struct grana {
		int v; ll c, f; int nx;
	};

	vector<grana> g;
	vector<int> start, used, d;

	maxflow(int n) : start(n, -1), used(n, -1), d(n, -1) {}

	void add_edge(int u, int v, ll c) {
		g.push_back({v, c, 0, start[u]});
		start[u] = g.size()-1;
		g.push_back({u, 0, 0, start[v]});
		start[v] = g.size()-1;
	}

	bool bfs(int s, int t) {
		basic_string<int> q = {s};
		size_t qs = 0;
		fill(d.begin(), d.end(), -1);
		d[s] = 0;
		while (qs != q.size()) {
			int x = q[qs++];
			for (int i=start[x]; i!=-1; i=g[i].nx) {
				int y = g[i].v;
				if (d[y] == -1 && g[i].c > g[i].f) {
					d[y] = d[x] + 1;
					q += y;
				}
			}
		}
		return d[t] != -1;
	}

	ll dfs(int x, int t, ll f=LINF) {
		if (x == t)
			return f;
		for (int& i=used[x]; i!=-1; i=g[i].nx) {
			int y = g[i].v;
			if (d[y] == d[x]+1 && g[i].c > g[i].f) {
				ll z = dfs(y, t, min(f, g[i].c - g[i].f));
				if (z > 0) {
					g[i].f += z;
					g[i^1].f -= z;
					return z;
				}
			}
		}
		return 0;
	}

	ll flow(int s, int t) {
		ll z = 0;
		while (bfs(s, t)) {
			used = start;
			while (1) {
				ll f = dfs(s, t);
				if (f > 0) {
					z += f;
				} else {
					break;
				}
			}
		}
		return z;
	}
};

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(nullptr);
	cout.tie(nullptr);
	cerr.tie(nullptr);

	cin >> n >> m;
	memset(d, 63, sizeof(d));
	for (int i=1; i<=n; i++)
		d[i][i] = 0;
	for (int i=0; i<m; i++) {
		int u, v;
		cin >> u >> v;
		if (u != v) {
			d[u][v] = 1;
			d[v][u] = 1;
		}
	}
	for (int i=1; i<=n; i++)
		for (int j=1; j<=n; j++)
			for (int k=1; k<=n; k++)
				d[j][k] = min(d[j][k], d[j][i] + d[i][k]);

	int s, b, k;
	cin >> s >> b >> k;
	for (int i=0; i<s; i++) {
		cin >> a[i].x >> a[i].a >> a[i].f >> a[i].p;
		a[i].i = i;
	}
	for (int i=0; i<b; i++) {
		cin >> c[i].x >> c[i].d >> c[i].g;
		zlato[c[i].x].emplace_back(c[i].d, c[i].g);
	}
	for (int i=1; i<=n; i++) {
		sort(zlato[i].begin(), zlato[i].end());
		zlato[i].emplace_back(2e9, -LINF);
		ll z = -LINF;
		for (auto& [x, y] : zlato[i]) {
			ll t = z;
			z = max(z, y);
			y = t;
		}
	}
	sort(a, a+s, [&](brod u, brod v) { return u.a < v.a; });
	for (int i=0; i<s; i++) {
		ll profit = -LINF;
		for (int x=1; x<=n; x++) {
			if (d[a[i].x][x] > a[i].f)
				continue;

			while (zlato[x][zlato_ptr[x]].first <= a[i].a)
				zlato_ptr[x]++;
			profit = max(profit, zlato[x][zlato_ptr[x]].second - a[i].p);
		}
		a[i].f = profit;
	}
	sort(a, a+s, [&](brod u, brod v) { return u.i < v.i; });
	// for (int i=0; i<s; i++)
		// cerr << i << " profit " << a[i].f << '\n';

	for (int i=0; i<k; i++) {
		cin >> dep[i].u >> dep[i].v;
		dep[i].u--;
		dep[i].v--;
		ugly[dep[i].u] = ugly[dep[i].v] = 1;
	}

	ll extra = 0;

	for (int i=0; i<s; i++) {
		if (ugly[i]) {
			ugly[i] = ++s2;
			p2[s2] = a[i].f;
		} else {
			extra += max(0ll, a[i].f);
		}
	}

	for (int i=0; i<k; i++) {
		df[ugly[dep[i].u]] += ugly[dep[i].v];
	}

	for (int i=1; i<=s2; i++) {
		dfs2(i, reach[i]);
	}

	for (int i=1; i<=s2; i++) {
		if (c3[i] == 0) {
			s3++;
			for (int j=1; j<=s2; j++) {
				if (reach[i][j] && reach[j][i]) {
					c3[j] = s3;
					p3[s3] += p2[j];
					p3[s3] = clamp(p3[s3], -LINF, LINF);
				}
			}
		}
	}

	for (int i=1; i<=s2; i++)
		for (int j : df[i])
			if (c3[i] != c3[j])
				e3[c3[i]] += c3[j];

	for (int i=1; i<=s3; i++) {
		sort(e3[i].begin(), e3[i].end());
		e3[i].resize(unique(e3[i].begin(), e3[i].end()) - e3[i].begin());
	}

	// flow?
	maxflow mf(s3+2);
	int source = 0;
	int sink = s3+1;
	for (int i=1; i<=s3; i++) {
		// cerr << "objekat " << i << " profita " << p3[i] << '\n';
		if (p3[i] < 0) {
			mf.add_edge(i, sink, -p3[i]);
		} else if (p3[i] > 0) {
			mf.add_edge(source, i, p3[i]);
			extra += p3[i];
		}
	}

	for (int i=1; i<=s3; i++)
		for (int j : e3[i]) {
			// cerr << i << " zavisi od " << j << '\n';
			mf.add_edge(i, j, LINF);
		}

	ll fl = mf.flow(source, sink);
	// cerr << "flow: " << fl << '\n';

	cout << extra - fl << '\n';
}

#include <bits/stdc++.h>
using namespace std;
#define sz(x) ((int) (x).size())

typedef long long ll;

const int INF2 = 100000;
int N, M;
int S, B;
ll K, H;
ll G[110][110];
vector<tuple<int,int,int,int,int>> sh;
vector<tuple<int,int,int>> bases;
ll maxR[110];
int in[100010];
int mapTo[100010];
vector<int> P2[100010];
vector<int> P[100010];
ll R[100010], R2[100010];
ll RESULT;
int newSI[100010];

typedef long long LL;

// Adjacency list implementation of FIFO push relabel maximum flow
// with the gap relabeling heuristic.  This implementation is
// significantly faster than straight Ford-Fulkerson.  It solves
// random problems with 10000 vertices and 1000000 edges in a few
// seconds, though it is possible to construct test cases that
// achieve the worst-case.
// Running time:
//     O(|V|^3)
// INPUT:
//     - graph, constructed using AddEdge()
//     - source, sink
// OUTPUT:
//     - maximum flow value
//     - To obtain the actual flow values, look at all edges with
//       capacity > 0 (zero capacity edges are residual edges).

const LL INF = 1e15;
struct Edge {
  int from, to;
  LL cap, flow;
  int index;
  Edge(int from, int to, LL cap, LL flow, int index) :
    from(from), to(to), cap(cap), flow(flow), index(index) {}
};

struct PushRelabel {
  int N; vector<vector<Edge> > G; vector<LL> excess;
  vector<int> dist, active, count; queue<int> Q;

  PushRelabel(int N) : N(N), G(N), excess(N), dist(N), active(N), count(2*N) {}

  void AddEdge(int from, int to, LL cap) {
    G[from].push_back(Edge(from, to, cap, 0, G[to].size()));
    if (from == to) G[from].back().index++;
    G[to].push_back(Edge(to, from, 0, 0, G[from].size() - 1));
  }

  void Enqueue(int v) {
    if (!active[v] && excess[v] > 0) { active[v] = true; Q.push(v); }
  }

  void Push(Edge &e) {
    LL amt = min(excess[e.from], LL(e.cap - e.flow));
    if (dist[e.from] <= dist[e.to] || amt == 0) return;
    e.flow += amt;
    G[e.to][e.index].flow -= amt;
    excess[e.to] += amt;
    excess[e.from] -= amt;
    Enqueue(e.to);
  }

  void Gap(int k) {
    for (int v = 0; v < N; v++) {
      if (dist[v] < k) continue;
      count[dist[v]]--;
      dist[v] = max(dist[v], N+1);
      count[dist[v]]++;
      Enqueue(v);
    }
  }

  void Relabel(int v) {
    count[dist[v]]--;
    dist[v] = 2*N;
    for (int i = 0; i < G[v].size(); i++)
      if (G[v][i].cap - G[v][i].flow > 0)
  dist[v] = min(dist[v], dist[G[v][i].to] + 1);
    count[dist[v]]++;
    Enqueue(v);
  }

  void Discharge(int v) {
    for (int i = 0; excess[v] > 0 && i < G[v].size(); i++) Push(G[v][i]);
    if (excess[v] > 0) {
      if (count[dist[v]] == 1)
  Gap(dist[v]);
      else
  Relabel(v);
    }
  }

  LL GetMaxFlow(int s, int t) {
    count[0] = N-1;
    count[N] = 1;
    dist[s] = N;
    active[s] = active[t] = true;
    for (int i = 0; i < G[s].size(); i++) {
      excess[s] += G[s][i].cap;
      Push(G[s][i]);
    }

    while (!Q.empty()) {
      int v = Q.front();
      Q.pop();
      active[v] = false;
      Discharge(v);
    }

    LL totflow = 0;
    for (int i = 0; i < G[s].size(); i++) totflow += G[s][i].flow;
    return totflow;
  }
};

void main2(int NN){
  /*
  for(int i=0; i<NN; i++){
    cout << R[i] << " (" << i << "): ";
    for(int x : P[i]){
      cout << x << " ";
    }
    cout << endl;
  }
  cout << "RES: " << RESULT << endl;
  */

  NN += 2;
  int source = NN-2, sink = NN-1;
  auto PR = PushRelabel(NN);
  ll sum = 0;
  for(int v= 0; v < NN-2;++v){
    if(R[v] >= 0){
      PR.AddEdge(source, v, R[v]);
      sum += R[v];
    }else{
      PR.AddEdge(v, sink, -R[v]);
    }
    for(int c : P[v]){
      PR.AddEdge(v, c, INF);
    }
  }
  LL res = sum-PR.GetMaxFlow(source, sink);
  cout << res + RESULT << endl;
}

int main(){
  cin >> N >> M;
  for(int i=0; i<N; i++){
    for(int j=0; j<N; j++){
      G[i][j] = INF;
    }
    G[i][i] = 0;
  }
  for(int i=0; i<M; i++){
    int u, v;
    cin >> u >> v;
    u--; v--;
    G[u][v] = 1;
    G[v][u] = 1;
  }
  cin >> S >> B >> K;
  for(int i=0; i<S; i++){
    int x, a, f, p;
    cin >> x >> a >> f >> p;
    x--;
    sh.push_back(make_tuple(a, x, f, p, i));
  }
  for(int i=0; i<B; i++){
    int x, d, g;
    cin >> x >> d >> g;
    x--;
    bases.push_back(make_tuple(d,x,g));
  }
  sort(sh.begin(), sh.end());
  sort(bases.begin(), bases.end());
  for(int k=0; k<N; k++){
    for(int i=0; i<N; i++){
      for(int j=0; j<N; j++){
        G[i][j] = min(G[i][j], G[i][k]+G[k][j]);
      }
    }
  }
  int bi=0;
  for(int i=0; i<N; i++){
    maxR[i] = -INF;
  }
  for(int i=0; i<S; i++){
    R2[i] = -INF;
    int xs, a, f, p, shInd;
    tie(a, xs, f, p, shInd) = sh[i];
    newSI[shInd] = i;
    for(; bi<B; bi++){
      int xb, d, g;
      tie(d, xb, g) = bases[bi];
      if(a < d){
        break;
      }
      maxR[xb] = max(maxR[xb], (ll)g);
    }
    //cout << "ship " << i << ": ";
    for(int j=0; j<N; j++){
      if(G[xs][j] <= f){
        //cout << "(->" << j << " " << maxR[j] << ") ";
        R2[i] = max(R2[i], maxR[j]-p);
      }
    }
    //cout << endl;
    //cout << R2[i] << " ";
  }
  //cout << endl;
  for(int i=0; i<K; i++){
    int u, v;
    cin >> u >> v;
    u--; v--;
    P2[newSI[u]].push_back(newSI[v]);
    in[newSI[v]]++;
    in[newSI[u]]++;
  }
  int cnt = 0;
  for(int i=0; i<S; i++){
    if(in[i]){
      R[cnt] = R2[i];
      mapTo[i] = cnt++;
    }
    else{
      RESULT += max(R2[i], 0ll);
    }
  }
  for(int i=0; i<S; i++){
    if(in[i]==0)
      continue;
    for(int x : P2[i]){
      P[mapTo[i]].push_back(mapTo[x]);
    }
  }
  main2(cnt);

  return 0;
}

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int inf=1e18, sz=2e3+10;

struct re
{
    int fr, to, cap;
};
int S, T, yk[sz], di[sz];
vector <int> sv[sz];
vector <re> edges;
void add_edge(int u, int v, int cap)
{
    sv[u].push_back(edges.size());
    edges.push_back({u, v, cap});
    sv[v].push_back(edges.size());
    edges.push_back({v, u, 0});// {v, u, cap} for bidirectional
}
bool bfs(int n)
{
    int qu[n], qf=0, qb=1;
    qu[0]=S;
    for(int a=0; a<n; a++) di[a]=inf;
    di[S]=0;
    while(qf<qb)
    {
        int v=qu[qf];
        for(int a=0; a<sv[v].size(); a++)
        {
            int i=sv[v][a];
            int ne=edges[i].to;
            if(di[ne]==inf and edges[i].cap>0)
            {
                di[ne]=di[v]+1, qu[qb]=ne, qb++;
            }
        }
        qf++;
    }
    return di[T]!=inf;
}
int dfs(int v, int flow)
{
    if(v==T) return flow;
    while(yk[v]<sv[v].size())
    {
        int i=sv[v][yk[v]];
        int ne=edges[i].to;
        if(di[ne]==di[v]+1 and edges[i].cap>0)
        {
            int re=dfs(ne, min(flow, edges[i].cap));
            if(re)
            {
                edges[i].cap-=re;
                edges[i^1].cap+=re;
                return re;
            }
        }
        yk[v]++;
    }
    return 0;
}
int dinic(int n)
{
    int flow=0;
    while(bfs(n))
    {
        for(int a=0; a<n; a++) yk[a]=0;
        while(1)
        {
            int add=dfs(S, inf);
            if(add) flow+=add;
            else break;
        }
    }
    return flow;
}

main()
{
    //freopen("input.txt", "r", stdin);
    int n, m;
    cin>>n>>m;
    int sm[n][n];
    for(int a=0; a<n; a++) for(int b=0; b<n; b++) sm[a][b]=(a==b) ? 0 : inf;
    for(int a=0; a<m; a++)
    {
        int u, v;
        scanf("%lld%lld", &u, &v);
        u--, v--;
        sm[u][v]=1, sm[v][u]=1;
    }
    for(int a=0; a<n; a++)
    {
        for(int b=0; b<n; b++)
        {
            for(int c=0; c<n; c++) sm[b][c]=min(sm[b][c], min(sm[b][a]+sm[a][c], inf));
        }
    }
    int shq, baq, k;
    cin>>shq>>baq>>k;
    int sh[shq][4];
    for(int a=0; a<shq; a++)
    {
        for(int b=0; b<4; b++) scanf("%lld", &sh[a][b]);
        sh[a][0]--;
    }
    vector <pair <int, int> > sp[n];
    for(int a=0; a<baq; a++)
    {
        int v, d, g;
        scanf("%lld%lld%lld", &v, &d, &g);
        v--;
        sp[v].push_back({d, g});
    }
    for(int a=0; a<n; a++)
    {
        sp[a].push_back({0, -inf});
        sort(sp[a].begin(), sp[a].end());
        for(int b=1; b<sp[a].size(); b++) sp[a][b].second=max(sp[a][b-1].second, sp[a][b].second);
    }
    int va[shq];
    for(int a=0; a<shq; a++)
    {
        va[a]=-inf;
        int v=sh[a][0], f=sh[a][1], di=sh[a][2], pri=sh[a][3];
        for(int b=0; b<n; b++)
        {
            if(sm[v][b]<=di)
            {
                int p=upper_bound(sp[b].begin(), sp[b].end(), make_pair(f, inf))-sp[b].begin();
                va[a]=max(va[a], sp[b][p-1].second);
            }
        }
        va[a]-=pri;
    }
    map <int, int> ma;
    int re[k][2], vq=0;
    for(int a=0; a<k; a++)
    {
        int u, v;
        scanf("%lld%lld", &u, &v);
        u--, v--;
        ma[u]=0, ma[v]=0;
        re[a][0]=u, re[a][1]=v;
    }
    for(auto it=ma.begin(); it!=ma.end(); it++) (*it).second=vq++;
    S=vq++, T=vq++;
    int an=0;
    for(int a=0; a<shq; a++)
    {
        if(ma.find(a)==ma.end()) an+=max(va[a], 0ll);
        else
        {
            if(va[a]>0) add_edge(S, ma[a], va[a]), an+=va[a];
            else add_edge(ma[a], T, -va[a]);
        }
    }
    for(int a=0; a<k; a++)
    {
        int u=ma[re[a][0]], v=ma[re[a][1]];
        add_edge(u, v, inf);
    }
    an-=dinic(vq);
    cout<<an;
}

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
#define FOR(i, a, b) for (int (i) = (a); (i) <= (b); (i)++)
#define ROF(i, a, b) for (int (i) = (a); (i) >= (b); (i)--)
#define REP(i, n) FOR(i, 0, (n)-1)
#define sqr(x) ((x) * (x))
#define all(x) (x).begin(), (x).end()
#define reset(x, y) memset(x, y, sizeof(x))
#define uni(x) (x).erase(unique(all(x)), (x).end())
#define BUG(x) cerr << #x << " = " << (x) << endl
#define pb push_back
#define eb emplace_back
#define mp make_pair
#define _1 first
#define _2 second
#define chkmin(a, b) a = min(a, b)
#define chkmax(a, b) a = max(a, b)

const int maxn = 112;
const int maxs = 112345;

struct Dinic { // can’t have negative cap!
#define int ll
#define maxn 2123
#define inf ll(1e14)

  struct Edge {
    int from, to, cap, flow;

    Edge(int from, int to, int cap, int flow) :
        from(from), to(to), cap(cap), flow(flow) {}
  };

  int n, m, s, t;
  vector<Edge> edges;
  vector<int> G[maxn];
  bool vis[maxn];
  int d[maxn];
  int cur[maxn];

  void init(int n) {
    this->n = n;
    for (int i = 0; i < n; i++) G[i].clear();
    edges.clear();
  }

  void addEdge(int from, int to, int cap) {
    edges.push_back(Edge(from, to, cap, 0));
    edges.push_back(Edge(to, from, 0, 0));
    m = edges.size();
    G[to].push_back(m - 1);
    G[from].push_back(m - 2);
  }

  bool bfs() {
    memset(vis, false, sizeof(vis));
    queue<int> Q;
    Q.push(s);
    d[s] = 0;
    vis[s] = true;
    while (!Q.empty()) {
      int x = Q.front();
      Q.pop();
      for (int i = 0; i < G[x].size(); i++) {
        Edge &e = edges[G[x][i]];
        if (!vis[e.to] && e.cap > e.flow) {
          vis[e.to] = true;
          d[e.to] = d[x] + 1;
          Q.push(e.to);
        }
      }
    }
    return vis[t];
  }

  int dfs(int x, int a) {
    if (x == t || a == 0) return a;
    int flow = 0, f;
    for (int &i = cur[x]; i < G[x].size(); i++) {
      Edge &e = edges[G[x][i]];
      if (d[x] + 1 == d[e.to] && (f = dfs(e.to, min(a, e.cap - e.flow))) > 0) {
        e.flow += f;
        edges[G[x][i] ^ 1].flow -= f;
        flow += f;
        a -= f;
        if (a == 0) break;
      }
    }
    return flow;
  }

  int maxflow(int s, int t) {
    this->s = s;
    this->t = t;
    int flow = 0;
    while (bfs()) {
      memset(cur, 0, sizeof(cur));
      flow += dfs(s, inf);
    }
    return flow;
  }

  void mincut(vector<int> &ans) { // Use after maxflow found
    bfs();
    for (int i = 0; i < m; i++) {
      Edge &e = edges[i];
      if (vis[e.from] && !vis[e.to] && e.cap > 0) ans.push_back(i);
    }
  }

#undef int
#undef maxn
#undef inf
};

struct SS {
  int x, a, f;
  ll p;
} s[maxs];

struct Base {
  int x, d, g;
} b[maxs];

int n, m, S, B, K;
int dis[maxn][maxn];
bool vis[maxs];

int main() {
  scanf("%d%d", &n, &m);
  reset(dis, 0x3f);
  while (m--) {
    int u, v;
    scanf("%d%d", &u, &v);
    dis[u][v] = dis[v][u] = 1;
  }
  FOR(i, 1, n) dis[i][i] = 0;
  FOR(k, 1, n) FOR(i, 1, n) FOR(j, 1, n) chkmin(dis[i][j], dis[i][k] + dis[k][j]);
  scanf("%d%d%d", &S, &B, &K);
  FOR(i, 1, S) scanf("%d%d%d%lld", &s[i].x, &s[i].a, &s[i].f, &s[i].p);
  FOR(i, 1, B) scanf("%d%d%d", &b[i].x, &b[i].d, &b[i].g);
  vector<pii> dep(K);
  for (auto &now : dep) {
    scanf("%d%d", &now._1, &now._2);
    vis[now._1] = vis[now._2] = true;
  }
  vector<vector<pii>> tab(n + 1);
  FOR(i, 1, B) tab[b[i].x].eb(b[i].d, b[i].g);
  FOR(i, 1, n) {
    sort(all(tab[i]));
    FOR(j, 1, int(tab[i].size()) - 1) chkmax(tab[i][j]._2, tab[i][j - 1]._2);
  }
  FOR(i, 1, S) {
    ll best = -2e9;
    FOR(j, 1, n) if (dis[s[i].x][j] <= s[i].f && !tab[j].empty()) {
      auto it = upper_bound(all(tab[j]), mp(s[i].a + 1, -1));
      if (it == tab[j].begin()) continue;
      it--;
      chkmax(best, ll(it->_2));
    }
    if (best == -2e9) s[i].p = -1e14;
    else s[i].p = best - s[i].p;
  }
  ll ans = 0;
  vector<int> spec;
  FOR(i, 1, S) {
    if (!vis[i] && s[i].p > 0) ans += s[i].p;
    else if (vis[i]) spec.eb(i);
  }
  Dinic solver;
  solver.init(spec.size() + 2);
  int st = spec.size(), en = st + 1;
  map<int, int> mat;
  REP(i, int(spec.size())) {
    if (s[spec[i]].p >= 0) {
      solver.addEdge(st, i, s[spec[i]].p);
      ans += s[spec[i]].p;
    }
    else solver.addEdge(i, en, -s[spec[i]].p);
    mat[spec[i]] = i;
  }
  for (auto it : dep) solver.addEdge(mat[it._1], mat[it._2], 1e14);
  ans -= solver.maxflow(st, en);
  printf("%lld", ans);
}

#ifdef LOCAL
#define _GLIBCXX_DEBUG
#endif // LOCAL
#include <bits/stdc++.h>

using namespace std;

using ll = long long;

#define pb push_back
#define sz(c) ((int)(c).size())

struct ship
{
    int id, pos, atk, fuel, price;

    bool operator < (const ship &o) const
    {
        return atk < o.atk;
    }
};

struct base
{
    int pos, def, gold;

    bool operator < (const base &o) const
    {
        return def < o.def;
    }
};

const ll inf_ll = ll(1e13);

struct edge
{
    int to;
    ll cap;
};

struct flow
{
    int n, s, t;
    vector<vector<int>> g;
    vector<edge> e;

    flow (int n_) : n(n_), s(n_ - 2), t(n_ - 1), g(n), e() {}

    void add_edge (int from, int to, ll cap)
    {
        g[from].pb(sz(e));
        e.pb(edge{to, cap});
        g[to].pb(sz(e));
        e.pb(edge{from, 0LL});
    }

    vector<int> dist, ptr;

    ll add_flow ()
    {
        dist.assign(n, -1);
        ptr.assign(n, 0);

        dist[s] = 0;
        queue<int> q;
        q.push(s);

        while (!q.empty())
        {
            int cur = q.front(); q.pop();
            for (int num : g[cur])
            {
                ll cap = e[num].cap;
                int to = e[num].to;
                if (cap > 0 && dist[to] == -1)
                {
                    dist[to] = dist[cur] + 1;
                    q.push(to);
                }
            }
        }

        return dfs(s, inf_ll);
    }

    ll dfs (int v, ll to_push)
    {
        if (v == t || to_push == 0)
            return to_push;

        ll pushed = 0;
        for (int &i = ptr[v]; i < sz(g[v]); i++)
        {
            const int num = g[v][i];
            const int to = e[num].to;
            const ll cap = e[num].cap;

            if (dist[to] == dist[v] + 1)
            {
                ll cur_push = dfs(to, min(to_push, cap));
                e[num].cap -= cur_push;
                e[num ^ 1].cap += cur_push;
                to_push -= cur_push;
                pushed += cur_push;
            }

            if (to_push == 0)
                break;
        }

        return pushed;
    }

    ll max_flow ()
    {
        ll ans = 0;
        while (ll add = add_flow())
            ans += add;
        return ans;
    }
};

ll solve_work_instr (const vector<vector<int>> &req, const vector<int> &reward, const vector<int> &cost)
{
    const int right = sz(reward), left = sz(cost);
    const ll sum_rew = accumulate(reward.begin(), reward.end(), 0LL);

    flow flow (2 + left + right);
    for (int i = 0; i < left; i++)
        flow.add_edge(flow.s, i, cost[i]);
    for (int i = 0; i < right; i++)
        flow.add_edge(left + i, flow.t, reward[i]);
    for (int i = 0; i < right; i++)
    {
        for (int instr : req[i])
            flow.add_edge(instr, left + i, inf_ll);
    }

    return sum_rew - flow.max_flow();
}

void dfs (int x, const vector<vector<int>> &g, vector<char> &used, vector<int> &reach)
{
    reach.pb(x);
    used[x] = 1;
    for (int dest : g[x]) if (!used[dest])
        dfs(dest, g, used, reach);
}

void solve(istream &cin = std::cin, ostream &cout = std::cout)
{
    int n, m;
    cin >> n >> m;

    const int inf = int(1e9) + 1;
    vector<vector<int>> dist(n, vector<int>(n, inf));
    for (int i = 0; i < n; i++)
        dist[i][i] = 0;

    for (int i = 0; i < m; i++)
    {
        int u, v;
        cin >> u >> v;
        --u, --v;
        dist[u][v] = dist[v][u] = 1;
    }

    for (int k = 0; k < n; k++)
    for (int i = 0; i < n; i++)
    for (int j = 0; j < n; j++)
        dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);

    int s, b, k;
    cin >> s >> b >> k;

    vector<ship> ship(s);
    vector<base> base(b);
    int cur_id = 0;
    for (auto &x : ship)
    {
        cin >> x.pos >> x.atk >> x.fuel >> x.price;
        --x.pos;
        x.id = cur_id++;
    }
    for (auto &x : base)
    {
        cin >> x.pos >> x.def >> x.gold;
        --x.pos;
    }

    sort(ship.begin(), ship.end());
    sort(base.begin(), base.end());

    vector<int> best_atk(s, -inf);
    vector<int> weak_base(n, -inf);
    int ptr = 0;

    for (auto x : ship)
    {
        while (ptr < sz(base) && base[ptr].def <= x.atk)
        {
            const int where = base[ptr].pos;
            const int gold = base[ptr].gold;
            weak_base[where] = max(weak_base[where], gold);
            ptr++;
        }

        for (int i = 0; i < n; i++)
        if (dist[i][x.pos] <= x.fuel)
            best_atk[x.id] = max(best_atk[x.id], weak_base[i] - x.price);
    }

    vector<vector<int>> g(s), grev(s);
    for (int i = 0; i < k; i++)
    {
        int x, y;
        cin >> x >> y;
        --x, --y;
        g[x].pb(y);
        grev[y].pb(x);
    }

    vector<int> instr;
    vector<vector<int>> req;
    vector<int> reward, cost;

    ll ans = 0;

    for (int i = 0; i < s; i++)
    {
        if (g[i].empty() && grev[i].empty())
            ans += max(0, best_atk[i]);
        else if (best_atk[i] < 0 && best_atk[i] > -inf)
            instr.pb(i);
    }

    sort(instr.begin(), instr.end());
    for (int i = 0; i < sz(instr); i++)
        cost.pb(-best_atk[instr[i]]);

    vector<char> used(s);

    for (int x : best_atk)
        cerr << x << ' ';
    cerr << endl;

    for (int i = 0; i < s; i++)
    if (!g[i].empty() || !grev[i].empty())
    {
        if (best_atk[i] >= 0)
        {
            vector<int> reach;
            dfs(i, g, used, reach);

            for (int x : reach)
                used[x] = 0;

            bool bad = false;
            for (int x : reach)
            if (best_atk[x] == -inf)
                bad = true;

            if (bad)
                continue;

            req.pb(vector<int>());
            reward.pb(best_atk[i]);

            for (int x : reach)
            if (best_atk[x] < 0)
            {
                int pos = lower_bound(instr.begin(), instr.end(), x) - instr.begin();
                assert(pos < sz(instr) && instr[pos] == x);
                req.back().pb(pos);
            }
        }
    }

    ans += solve_work_instr (req, reward, cost);
    cout << ans << endl;
}

int main()
{
	ios_base::sync_with_stdio(false);
	cin.tie(nullptr);

	cout << fixed;

#ifdef LOCAL
	ifstream fin("input.txt");

	solve(fin);

	cout << setprecision(4) << "clock: " << clock() / (double) CLOCKS_PER_SEC << endl;
#else
	cout << setprecision(20);

	solve();
#endif

	return 0;
}

#include <bits/stdc++.h>
#define mp make_pair
#define pb push_back
#define pii pair<int,int>
#define st first
#define nd second
#define endl '\n'
using namespace std;
// Adjacency list implementation of FIFO push relabel maximum flow
// with the gap relabeling heuristic.  This implementation is
// significantly faster than straight Ford-Fulkerson.  It solves
// random problems with 10000 vertices and 1000000 edges in a few
// seconds, though it is possible to construct test cases that
// achieve the worst-case.
// Running time:
//     O(|V|^3)
// INPUT:
//     - graph, constructed using AddEdge()
//     - source, sink
// OUTPUT:
//     - maximum flow value
//     - To obtain the actual flow values, look at all edges with
//       capacity > 0 (zero capacity edges are residual edges).

typedef long long LL;

struct Edge {
	LL from, to, cap, flow, index;
	Edge(int from, int to, LL cap, LL flow, int index) :
		from(from), to(to), cap(cap), flow(flow), index(index) {}
};

struct PushRelabel {
	int N; vector<vector<Edge>> G;
	vector<int> dist, active, count;
	vector<LL> excess; queue<int> Q;

	PushRelabel(int N) : N(N), G(N), excess(N), dist(N), active(N), count(2 * N) {}

	void AddEdge(int from, int to, LL cap) {
		G[from].push_back(Edge(from, to, cap, 0, G[to].size()));
		if(from == to) G[from].back().index++;
		G[to].push_back(Edge(to, from, 0, 0, G[from].size() - 1));
	}

	void Enqueue(int v) {
		if(!active[v] && excess[v] > 0) {
			active[v] = true;
			Q.push(v);
		}
	}

	void Push(Edge &e) {
		LL amt = min(excess[e.from], e.cap - e.flow);
		if(dist[e.from] <= dist[e.to] || amt == 0) return;
		e.flow += amt;
		G[e.to][e.index].flow -= amt;
		excess[e.to] += amt;
		excess[e.from] -= amt;
		Enqueue(e.to);
	}

	void Gap(int k) {
		for(int v = 0; v < N; v++) {
			if(dist[v] < k) continue;
			count[dist[v]]--;
			dist[v] = max(dist[v], N + 1);
			count[dist[v]]++;
			Enqueue(v);
		}
	}

	void Relabel(int v) {
		count[dist[v]]--;
		dist[v] = 2 * N;
		for(int i = 0; i < G[v].size(); i++)
			if(G[v][i].cap - G[v][i].flow > 0)
				dist[v] = min(dist[v], dist[G[v][i].to] + 1);
		count[dist[v]]++;
		Enqueue(v);
	}

	void Discharge(int v) {
		for(int i = 0; excess[v] > 0 && i < G[v].size(); i++) Push(G[v][i]);
		if(excess[v] > 0) {
			if(count[dist[v]] == 1)
				Gap(dist[v]);
			else
				Relabel(v);
		}
	}

	LL GetMaxFlow(int s, int t) {
		count[0] = N - 1;
		count[N] = 1;
		dist[s] = N;
		active[s] = active[t] = true;
		for(int i = 0; i < G[s].size(); i++) {
			excess[s] += G[s][i].cap;
			Push(G[s][i]);
		}

		while(!Q.empty()) {
			int v = Q.front();
			Q.pop();
			active[v] = false;
			Discharge(v);
		}

		LL totflow = 0;
		for(int i = 0; i < G[s].size(); i++) totflow += G[s][i].flow;
		return totflow;
	}
};

const int INF = 1e5;
LL dis[101][101], n, m, u, v, gold[101], po[101], go, vis[100005];
LL ans, tot[100005];
vector<pii> bases[101];
LL xs[100005], a[100005], f[100005], p[100005];
LL xb[100005], d[100005], g[100005];
vector<pii> ships;

int main() {
	ios_base::sync_with_stdio(0);
	cin.tie(0);
	cin >> n >> m;
	for(int i = 1; i <= n; ++i)
		for(int j = 1; j <= n; ++j) {
			if(j != i)
				dis[i][j] = INF;
		}
	for(int i = 0; i < m; ++i) {
		cin >> u >> v;
		if(u != v)
			dis[u][v] = dis[v][u] = 1;
	}
	for(int b = 1; b <= n; ++b)
		for(int a = 1; a <= n; ++a)
			for(int c = 1; c <= n; ++c)
				dis[a][c] = min(dis[a][c], dis[a][b] + dis[b][c]);
	int s, b, k;
	cin >> s >> b >> k;
	for(int i = 0; i < s; ++i) {
		cin >> xs[i] >> a[i] >> f[i] >> p[i];
		ships.pb(mp(a[i], i));
	}
	for(int i = 0; i < b; ++i) {
		cin >> xb[i] >> d[i] >> g[i];
		bases[xb[i]].pb(mp(d[i], g[i]));
	}
	for(int i = 1; i <= n; ++i)
		sort(bases[i].begin(), bases[i].end());
	sort(ships.begin(), ships.end());
  for (int j = 1; j <= n; j++)
    gold[j] = - (1LL << 55);
	for(int i = 0; i < s; ++i) {
		for(int j = 1; j <= n; ++j)
			while(po[j] != (int) bases[j].size() && bases[j][po[j]].st <= ships[i].st)
				gold[j] = max(gold[j], (LL) bases[j][po[j]++].nd);
		go = - (1LL << 55);
		u = ships[i].nd;
		for(int j = 1; j <= n; ++j)
			if(dis[j][xs[u]] < INF && dis[j][xs[u]] <= f[u]) {
				go = max(go, gold[j]);
			}
		tot[u] = go - p[u];
	}
  PushRelabel pr(s + 2);
  LL ls = 0;
  for (int i = 0; i < s; i++) {
    if (tot[i] > 0)
      ls += tot[i], pr.AddEdge(0, i + 2, tot[i]);
    else
      pr.AddEdge(i + 2, 1, -tot[i]);
  }
	for(int i = 0; i < k; ++i) {
		cin >> u >> v, u--, v--;
    pr.AddEdge(u + 2, v + 2, (1LL << 55));
	}
  ls -= pr.GetMaxFlow(0, 1);
  cout << ls << "\n";
}

#include<bits/stdc++.h>
#define re register
#define inc(i,j,k) for(re int i=j;i<=k;i++)
#define dec(i,j,k) for(re int i=j;i>=k;i--)
#define ll long long
#define int long long
using namespace std;
const int MAXN=105;
const int MAXM=100005;
const ll inf=100000000000000;
inline int read(){
	int x=0,f=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while('0'<=ch&&ch<='9'){x=x*10+ch-'0',ch=getchar();}
	return f*x;
}
int n,m,s,b,dis[MAXN][MAXN],a,c,x,f,p,val,d,g,ru[MAXM],cnt=1,head[MAXM],t,S,T,dep[MAXM],tmp;
ll ans,dp[MAXM];
inline void floyd(){
	inc(k,1,n){
		inc(i,1,n){
			inc(j,1,n) dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
		}
	}
}
struct spaceship{
	int a,f,p,val,num;
	bool flag;
	spaceship(int aa,int ff,int pp,int vval,bool fflag,int nnum){a=aa,f=ff,p=pp,val=vval,flag=fflag,num=nnum;}
};
struct castal{
	int d,g;
	castal(int dd,int gg){d=dd,g=gg;}
};
vector<spaceship> ship[MAXN];
vector<castal> cas[MAXN],cass[MAXN];
bool cmp1(spaceship x,spaceship y){return x.a<y.a;}
bool cmp2(castal x,castal y){return x.d<y.d;}
struct egde{
	int to,nxt;
	ll flow;
}e[MAXM<<2];
bool use[MAXM];
inline void add(int a,int b,ll c){
	e[++cnt].to=b;
	e[cnt].nxt=head[a];
	head[a]=cnt;
	e[cnt].flow=c;
}
bool bfs(){
	queue<int> q;
	inc(i,0,s+1) dep[i]=-1;
	q.push(S),dep[S]=1;
	while(q.size()){
		int u=q.front();
		q.pop();
		for(re int i=head[u];i;i=e[i].nxt){
			int v=e[i].to;
			if(dep[v]==-1&&e[i].flow){
				dep[v]=dep[u]+1;
				q.push(v);
			}
		}
	}
	return dep[T]!=-1;
}
ll dfs(int u,ll f){
	if(u==T) return f;
	ll res=f,k=0;
	for(re int i=head[u];i;i=e[i].nxt){
		int v=e[i].to;
		if(dep[u]+1==dep[v]&&e[i].flow){
			k=dfs(v,min(f,e[i].flow));
			if(!k) dep[v]=-1;
			e[i].flow-=k;
			e[i^1].flow+=k;
			res-=k;
		}
	}
	return f-res;
}
signed main(){
	n=read(),m=read();
	inc(i,1,n){
		inc(j,1,n) dis[i][j]=1000;
	}
	inc(i,1,n) dis[i][i]=0;
	inc(i,1,m){
		a=read(),c=read();
		dis[c][a]=dis[a][c]=1;
	}
	floyd();
	s=read(),b=read(),t=read();
	S=0,T=s+1;
	inc(i,1,s){
		x=read(),a=read(),f=read(),p=read();
		ship[x].push_back(spaceship(a,f,p,0,0,i));
	}
	inc(i,1,b){
		x=read(),d=read(),g=read();
		cas[x].push_back(castal(d,g));
	}
	inc(i,1,n) sort(ship[i].begin(),ship[i].end(),cmp1);
	inc(i,1,n) sort(cas[i].begin(),cas[i].end(),cmp2);
	inc(i,1,n){
		for(re int j=0;j<cas[i].size();j++){
			while(j<cas[i].size()&&cass[i].size()&&cas[i][j].g<cass[i][cass[i].size()-1].g) j++;
			if(j>=cas[i].size()) break;
			cass[i].push_back(cas[i][j]);
		}
	}
	inc(i,1,n){
		inc(j,1,n){
			if(!cass[j].size()) continue;
			int l=-1;
			for(re int k=0;k<ship[i].size();k++){
				while(l+1<cass[j].size()&&cass[j][l+1].d<=ship[i][k].a) l++;
				if(l!=-1&&ship[i][k].f>=dis[i][j]) ship[i][k].flag=1,ship[i][k].val=max(ship[i][k].val,cass[j][l].g);
			}
		}
	}
	inc(i,1,n){
		for(re int j=0;j<ship[i].size();j++){
			use[ship[i][j].num]=ship[i][j].flag;
			if(use[ship[i][j].num]) dp[ship[i][j].num]=ship[i][j].val-ship[i][j].p;
			else dp[ship[i][j].num]=-inf;
			ans+=max((ll)0,dp[ship[i][j].num]);
		}
	}
	inc(i,1,t){
		a=read(),c=read();
		add(a,c,inf),add(c,a,0);
	}
	inc(i,1,s){
		if(dp[i]>0) add(S,i,dp[i]),add(i,S,0);
		else if(dp[i]<0) add(i,T,-dp[i]),add(T,i,0);
	}
	while(bfs()) while(tmp=dfs(S,inf)) ans-=tmp;
	printf("%I64d",ans);
}

#include <bits/stdc++.h>

using namespace std;

typedef long long int LL;

#define st first
#define nd second
#define PII pair <int, int>

namespace Dinic{
	typedef LL T;
	const int N = 100005;
	const T INF = 1000LL * 1000 * 1000 * 1000 * 1000 * 1000;

	struct edge{
		int a, b;
		T cap, flow;
	};

	int n, s, t, d[N], ptr[N], q[N];
	vector <edge> e;
	vector <int> g[N];

	int add_edge(int a, int b, T cap){
		edge e1 = {a, b, cap, 0};
		edge e2 = {b, a, cap, cap};

		g[a].push_back(e.size());
		e.push_back(e1);
		g[b].push_back(e.size());
		e.push_back(e2);
		return e.size() - 2;
	}

	bool bfs(){
		int qh = 0, qt = 0;
		q[qt++] = s;
		memset(d + 1, -1, n * sizeof d[0]);
		d[s] = 0;

		while(qh < qt && d[t] == -1){
			int v = q[qh++];
			for(int i = 0; i < (int)g[v].size(); ++i){
				int id = g[v][i], to = e[id].b;
				if(d[to] == -1 && e[id].flow < e[id].cap){
					q[qt++] = to;
					d[to] = d[v] + 1;
				}
			}
		}

		return d[t] != -1;
	}

	T dfs(int v, T flow){
		if(!flow)	return 0;
		if(v == t)	return flow;
		T res = 0;
		for(; ptr[v] < (int)g[v].size(); ++ptr[v]){
			int id = g[v][ptr[v]], to = e[id].b;
			if(d[to] != d[v] + 1)	continue;
			T pushed = dfs(to, min(flow, e[id].cap - e[id].flow));
			e[id].flow += pushed;
			e[id ^ 1].flow -= pushed;
			res += pushed;
			flow -= pushed;
			if(flow == 0)	break;
		}

		return res;
	}

	T dinic(int _n, int _s, int _t){
		n = _n; s = _s; t = _t;
		T flow = 0;
		for(;;){
			if(!bfs())	break;
			memset(ptr, 0, n * sizeof ptr[0]);
			flow += dfs(s, INF);
		}
		return flow;
	}
}

const int N = 107;
const int NN = 100007;

const int MAXI = 1e6;
const int INF = 1e9 + 7;

int n, m;
int dist[N][N];

int s, b, k;
int pl2[NN], def[NN], gold[NN];
int pl1[NN], att[NN], fuel[NN], price[NN], profit[NN];

vector <int> A[N], B[N];

bool cmp(int a, int b){
	if(att[a] == att[b])	return a < b;
	return att[a] < att[b];
}

bool cmp2(int a, int b){
	if(def[a] == def[b])	return a < b;
	return def[a] < def[b];
}

int main(){
	scanf("%d %d", &n, &m);
	for(int i = 1; i <= n; ++i)
		for(int j = 1; j <= n; ++j)
			dist[i][j] = i == j ? 0 : INF;

	for(int i = 1; i <= m; ++i){
		int u, v;
		scanf("%d %d", &u, &v);

		if(u == v)	continue;
		dist[u][v] = dist[v][u] = 1;
	}

	for(int k = 1; k <= n; ++k)
		for(int i = 1; i <= n; ++i)
			for(int j = 1; j <= n; ++j)
				dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);

	scanf("%d %d %d", &s, &b, &k);
	for(int i = 1; i <= s; ++i){
		scanf("%d %d %d %d", &pl1[i], &att[i], &fuel[i], &price[i]);
		A[pl1[i]].push_back(i);
	}

	for(int i = 1; i <= b; ++i){
		scanf("%d %d %d", &pl2[i], &def[i], &gold[i]);
		B[pl2[i]].push_back(i);
	}

	for(int i = 1; i <= n; ++i){
		sort(A[i].begin(), A[i].end(), cmp);
		sort(B[i].begin(), B[i].end(), cmp2);
	}

	for(int i = 1; i <= n; ++i)
		for(int j = 1; j < (int)B[i].size(); ++j)
			gold[B[i][j]] = max(gold[B[i][j]], gold[B[i][j - 1]]);

	for(int i = 1; i <= n; ++i){
		if(A[i].size() == 0)	continue;
		for(auto t: A[i])
			profit[t] = -INF;

		for(int j = 1; j <= n; ++j){
			if(B[j].size() == 0)	continue;
			int wsk = -1;

			for(int t: A[i]){
				while(wsk + 1 < (int)B[j].size() && def[B[j][wsk + 1]] <= att[t])
					++wsk;

				if(wsk > -1 && fuel[t] >= dist[i][j])
					profit[t] = max(profit[t], gold[B[j][wsk]] - price[t]);
			}
		}
	}

	for(int i = 1; i <= s; ++i){
		LL weight = 1LL * MAXI * profit[i];
		if(profit[i] == -INF)	weight = -Dinic::INF;
		if(weight == 0)	weight = 1;

		if(weight > 0)
			Dinic::add_edge(1, i + 1, weight);
		else
			Dinic::add_edge(i + 1, s + 2, -weight);
	}

	for(int i = 1; i <= k; ++i){
		int u, v;
		scanf("%d %d", &u, &v);
		Dinic::add_edge(u + 1, v + 1, Dinic::INF);
	}

	LL ans = 0LL;
	for(int i = 1; i <= s; ++i)
		if(profit[i] > 0)
			ans += profit[i];

	ans -= Dinic::dinic(s + 2, 1, s + 2) / MAXI;
	printf("%lld\n", ans);
	return 0;
}

#include <bits/stdc++.h>
#define db(x) cout << (x) << '\n';
using namespace std;
typedef long long ll;
typedef pair<ll,ll> pii;
#define MAXN 105
#define oo2 ((ll)(1e9+7))
#define MAXM 100005

ll d[MAXN][MAXN];
vector<pii> bs[MAXN];
ll mbs[MAXN][MAXM],pl[MAXM],pp[MAXM][4];

template<typename flow_type>
struct dinic
{
	struct edge
	{
		size_t src, dst, rev;
		flow_type flow, cap;
	};

	int n;
	vector<vector<edge>> adj;

	dinic(int n) : n(n), adj(n), level(n), q(n), it(n) {}

	void add_edge(size_t src, size_t dst, flow_type cap, flow_type rcap = 0)
	{
		adj[src].push_back({src, dst, adj[dst].size(), 0, cap});
		if (src == dst) adj[src].back().rev++;
		adj[dst].push_back({dst, src, adj[src].size() - 1, 0, rcap});
	}

	vector<int> level, q, it;

	bool bfs(int source, int sink)
	{
		fill(level.begin(), level.end(), -1);
		for (int qf = level[q[0] = sink] = 0, qb = 1; qf < qb; ++qf)
		{
			sink = q[qf];
			for (edge &e : adj[sink])
			{
				edge &r = adj[e.dst][e.rev];
				if (r.flow < r.cap && level[e.dst] == -1)
					level[q[qb++] = e.dst] = 1 + level[sink];
			}
		}
		return level[source] != -1;
	}

	flow_type augment(int source, int sink, flow_type flow)
	{
		if (source == sink) return flow;
		for (; it[source] != adj[source].size(); ++it[source])
		{
			edge &e = adj[source][it[source]];
			if (e.flow < e.cap && level[e.dst] + 1 == level[source])
			{
				flow_type delta = augment(e.dst, sink,
								  min(flow, e.cap - e.flow));
				if (delta > 0)
				{
					e.flow += delta;
					adj[e.dst][e.rev].flow -= delta;
					return delta;
				}
			}
		}
		return 0;
	}

	flow_type max_flow(int source, int sink)
	{
		for (int u = 0; u < n; ++u)
			for (edge &e : adj[u]) e.flow = 0;
		flow_type flow = 0;
		flow_type oo = numeric_limits<flow_type>::max();

		while (bfs(source, sink))
		{
			fill(it.begin(), it.end(), 0);
			for (flow_type f; (f = augment(source, sink, oo)) > 0;)
				flow += f;

		} // level[u] = -1 => source side of min cut
		return flow;
	}
};

int main()
{
    ios_base::sync_with_stdio(0);
    cin.tie(0);

    ll n,m,u,v;
    cin >> n >> m;
    for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
            d[i][j]=oo2;
    for(ll i=0;i<m;i++)
    {
        cin >> u >> v;
        u--,v--;
        d[u][v]=d[v][u]=1;
    }

    for(int i=0;i<n;i++)
        d[i][i]=0;
    for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
            for(int k=0;k<n;k++)
                d[j][k]=min(d[j][k],d[j][i]+d[i][k]);

    ll s,b,k,gg,de;
    cin >> s >> b >> k;
    for(ll i=0;i<s;i++)
    {
        cin >> pp[i][0] >> pp[i][1] >> pp[i][2] >> pp[i][3];
        pp[i][0]--;
        pl[i]=-(oo2*oo2);
    }
    for(int i=0;i<b;i++)
    {
        cin >> u >> de >> gg;
        u--;
        bs[u].push_back(pii(de,gg));
    }

    for(int i=0;i<n;i++)
    {
        sort(bs[i].begin(),bs[i].end());
        ll ma=0;
        for(ll j=0;j<bs[i].size();j++)
        {
            ma=max(ma,bs[i][j].second);
            mbs[i][j]=ma;
        }
    }

    dinic<ll> g(2+s);
    ll s1=0;
    for(int i=0;i<s;i++)
    {
        ll ma=0;
        bool ok=0;
        for(int j=0;j<n;j++)
        {
            if(d[j][pp[i][0]]>pp[i][2])
                continue;
            ll pos=upper_bound(bs[j].begin(),bs[j].end(),pii(pp[i][1],oo2))-bs[j].begin();
            if(pos)
                ma=max(ma,mbs[j][pos-1]),ok=1;
        }
        if(ok)
            pl[i]=ma-pp[i][3];
        if(pl[i]>0)
        {
            g.add_edge(0,i+1,pl[i]);
            s1+=pl[i];
        }
        if(pl[i]<0)
            g.add_edge(i+1,s+1,-pl[i]);
    }

    for(ll i=0;i<k;i++)
    {
        cin >> u >> v;
        g.add_edge(u,v,oo2*oo2);
    }

    db(s1-g.max_flow(0,s+1))

    return 0;
}

#include<bits/stdc++.h>
using namespace std;

#define ll long long
#define all(aaa) aaa.begin(), aaa.end()

struct E {
    int to, i;
};

const ll INF = 1e18;
const int N = 105, M = 1e5 + 5, V = 2005, Z = 3e6, S = V - 2, T = V - 1;
int best[M], pos[M], atk[M], fuel[M], dt[V], p[V];
ll cp[Z], fl[Z], d[N][N], cost[M];
int ce = 0;
vector<E> g[V];
vector<pair<int, int>> lt[N];
bool notFree[M], loser[M];

void addEdge(int a, int b, ll c) {
    cp[ce] = c;
    g[a].push_back({b, ce++});
    cp[ce] = 0;
    g[b].push_back({a, ce++});
}

bool bfs() {
    queue<int> q;
    fill(dt, dt + V, -1);
    dt[S] = 0;
    q.push(S);

    while (!q.empty()) {
        int node = q.front();
        q.pop();
        for (E e : g[node]) {
            if (cp[e.i] > fl[e.i] && dt[e.to] == -1) {
                dt[e.to] = dt[node] + 1;
                q.push(e.to);
            }
        }
    }

    return dt[T] != -1;
}

ll dfs(int node, ll flow) {
    if (node == T)
        return flow;
    for (int &i = p[node]; i < g[node].size(); i++) {
        E e = g[node][i];
        if (cp[e.i] > fl[e.i] && dt[e.to] == dt[node] + 1)  {
            int ret = dfs(e.to, min(flow, cp[e.i] - fl[e.i]));
            if (ret) {
                fl[e.i] += ret;
                fl[e.i ^ 1] -= ret;
                return ret;
            }
        }
    }
    return 0;
}

ll maxFlow() {
    ll flow = 0;
    while (bfs()) {
        memset(p, 0, sizeof(p));
        ll ret = 0;
        while (ret = dfs(S, INF)) {
            flow += ret;
        }
    }
    return flow;
}

signed main() {
#ifdef HOME
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#endif
    ios_base::sync_with_stdio(0);
    cin.tie(0);

    int n, m;
    cin >> n >> m;

    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            d[i][j] = INF;
        }
        d[i][i] = 0;
    }

    for (int i = 0; i < m; i++) {
        int a, b;
        cin >> a >> b;
        a--, b--;
        d[b][a] = d[a][b] = 1;
    }

    for (int i = 0; i < n; i++)  {
        for (int j = 0; j < n; j++) {
            for (int k = 0; k < n; k++) {
                d[j][k] = min(d[j][i] + d[i][k], d[j][k]);
            }
        }
    }

    int s, b, k;
    cin >> s >> b >> k;

    for (int i = 0; i < s; i++) {
        cin >> pos[i] >> atk[i] >> fuel[i] >> cost[i];
        pos[i]--;
    }

    for (int i = 0; i < b; i++) {
        int pl, def, gold;
        cin >> pl >> def >> gold;
        pl--;
        lt[pl].push_back({def, gold});
    }

    for (int i = 0; i < n; i++) {
        lt[i].push_back({0, 0});
        sort(all(lt[i]));
        for (int j = 1; j < lt[i].size(); j++) {
            lt[i][j].second = max(lt[i][j].second, lt[i][j - 1].second);
        }
    }

    for (int i = 0; i < s; i++) {
        loser[i] = true;
        for (int j = 0; j < n; j++) {
            if (d[pos[i]][j] <= fuel[i]) {
                int q = upper_bound(lt[j].begin(), lt[j].end(), make_pair(atk[i] + 1, -1)) - lt[j].begin();
                if (q > 1)
                    loser[i] = false;
                best[i] = max(best[i], lt[j][q - 1].second);
            }
        }
    }

    vector<int> vip;
    vector<pair<int, int>> dep;

    for (int i = 0; i < k; i++) {
        int a, b;
        cin >> a >> b;
        a--, b--;
        vip.push_back(a);
        vip.push_back(b);

        notFree[a] = notFree[b] = 1;

        dep.push_back({a, b});
    }

    sort(all(vip));
    vip.erase(unique(all(vip)), vip.end());

    ll ans = 0;

    for (int i = 0; i < s; i++) {
        if (!notFree[i] && best[i] > cost[i]) {
            ans += best[i] - cost[i];
            // cout << best[i] - cost[i] << "\n";
        }
    }

    for (int i = 0; i < vip.size(); i++) {
        if (loser[vip[i]])
            cost[vip[i]] = INF;

        addEdge(S, i, cost[vip[i]]);
        addEdge(i, T, best[vip[i]]);
        ans += best[vip[i]];
    }

    for (auto e : dep) {
        e.first = lower_bound(all(vip), e.first) - vip.begin();
        e.second = lower_bound(all(vip), e.second) - vip.begin();
        addEdge(e.second, e.first, INF);
    }

    ans -= maxFlow();

    cout << ans;

    return 0;
}

#include<bits/stdc++.h>
using namespace std;

const long long inf=1000000000000000000ll;
vector<pair<int,int> > v[110];
struct spaceship{int x,a,f; long long p;}s[100010];
int n,m,p[110],f[110][110],x,y,id[100010],d,g,S,B,K,D[100010],e[100010][2];

bool cmp(const int &a,const int &b) {return s[a].a<s[b].a;}

namespace MaxFlow
{
	struct node{int to,next; long long c;}e[100010];
	int hd[10010],cnt,n,cur[10010],dis[10010],q[10010],l,r,x;
	void addedge(int x,int y,long long c)
	{
		e[++cnt]=(node){y,hd[x],c},hd[x]=cnt;
		e[++cnt]=(node){x,hd[y],0},hd[y]=cnt;
	}
	bool bfs()
	{
		for (int i=1; i<=n; i++) dis[i]=0;
		dis[1]=1,q[l=r=1]=1;
		while (l<=r)
		{
			x=q[l++];
			for (int i=hd[x]; i; i=e[i].next)
				if (e[i].c>0&&!dis[e[i].to]) dis[e[i].to]=dis[x]+1,q[++r]=e[i].to;
		}
		return (dis[n]>0);
	}
	long long dinic(int x,long long f)
	{
		if (x==n) return f;
		for (int &i=cur[x]; i; i=e[i].next)
			if (e[i].c>0&&dis[e[i].to]==dis[x]+1)
			{
				long long nw=dinic(e[i].to,min(f,e[i].c));
				if (nw>0) return e[i].c-=nw,e[i^1].c+=nw,nw;
			}
		return 0;
	}
	long long solve()
	{
		long long ans=0,nw;
		while (bfs())
		{
			for (int i=1; i<=n; i++) cur[i]=hd[i];
			while (nw=dinic(1,inf)) ans+=nw;
		}
		return ans;
	}
}

int main()
{
	scanf("%d%d",&n,&m);
	for (int i=1; i<=n; i++)
		for (int j=1; j<=n; j++) f[i][j]=100000;
	for (int i=1; i<=m; i++) scanf("%d%d",&x,&y),f[x][y]=f[y][x]=1;
	for (int k=1; k<=n; k++)
		for (int i=1; i<=n; i++)
			for (int j=1; j<=n; j++)
				f[i][j]=min(f[i][j],f[i][k]+f[k][j]);
	scanf("%d%d%d",&S,&B,&K);
	for (int i=1; i<=S; i++) id[i]=i,scanf("%d%d%d%d",&s[i].x,&s[i].a,&s[i].f,&s[i].p);
	sort(id+1,id+1+S,cmp);
	for (int i=1; i<=B; i++) scanf("%d%d%d",&x,&d,&g),v[x].push_back(make_pair(d,g));
	for (int i=1 ;i<=n; i++)
	{
		sort(v[i].begin(),v[i].end()),p[i]=0;
		for (int j=1,sz=v[i].size(); j<sz; j++)
			v[i][j].second=max(v[i][j].second,v[i][j-1].second);
	}
	long long ans=0;
	for (int I=1; I<=S; I++)
	{
		int i=id[I];
		long long ma=-inf;
		for (int j=1; j<=n; j++)
			if (f[s[i].x][j]<=s[i].f)
			{
				int sz=v[j].size();
				if (!sz) continue;
				while (p[j]<sz-1&&v[j][p[j]+1].first<=s[i].a) p[j]++;
				if (v[j][p[j]].first<=s[i].a) ma=max(ma,(long long)v[j][p[j]].second);
			}
		s[i].p=ma-s[i].p;
		if (s[i].p>0) ans+=s[i].p;
	}
	MaxFlow::n=2,MaxFlow::cnt=1;
	for (int i=1; i<=K; i++) scanf("%d%d",&e[i][0],&e[i][1]),D[e[i][0]]++,D[e[i][1]]++;
	for (int i=1; i<=S; i++) if (D[i]) id[i]=(MaxFlow::n++);
	for (int i=1; i<=K; i++) MaxFlow::addedge(id[e[i][0]],id[e[i][1]],inf);
	for (int i=1; i<=S; i++) if (D[i])
	{
		if (s[i].p>0) MaxFlow::addedge(1,id[i],s[i].p);
		else MaxFlow::addedge(id[i],MaxFlow::n,-s[i].p);
	}
	ans-=MaxFlow::solve();
	printf("%I64d\n",ans);
	return 0;
}

    #include <bits/stdc++.h>
    #define fst first
    #define snd second
    #define fore(i,a,b) for(int i=a,ThxDem=b;i<ThxDem;++i)
    #define pb push_back
    #define ALL(s) s.begin(),s.end()
    #define FIN ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0)
    #define SZ(s) int(s.size())
    using namespace std;
    typedef long long ll;
    typedef pair<ll,ll> ii;

    ll d[110][110],INF=1e18;
    ll v[100010];
    vector<ii> base[110];
    vector<ll> bst[110];

    // Min cut: nodes with dist>=0 vs nodes with dist<0
    // Matching MVC: left nodes with dist<0 + right nodes with dist>0
    struct Dinic{
    	int nodes,src,dst;
    	vector<int> dist,q,work;
    	struct edge {int to,rev;ll f,cap;};
    	vector<vector<edge>> g;
    	Dinic(int x):nodes(x),g(x),dist(x),q(x),work(x){}
    	void add_edge(int s, int t, ll cap){
    		g[s].pb((edge){t,SZ(g[t]),0,cap});
    		g[t].pb((edge){s,SZ(g[s])-1,0,0});
    	}
    	bool dinic_bfs(){
    		fill(ALL(dist),-1);dist[src]=0;
    		int qt=0;q[qt++]=src;
    		for(int qh=0;qh<qt;qh++){
    			int u=q[qh];
    			fore(i,0,SZ(g[u])){
    				edge &e=g[u][i];int v=g[u][i].to;
    				if(dist[v]<0&&e.f<e.cap)dist[v]=dist[u]+1,q[qt++]=v;
    			}
    		}
    		return dist[dst]>=0;
    	}
    	ll dinic_dfs(int u, ll f){
    		if(u==dst)return f;
    		for(int &i=work[u];i<SZ(g[u]);i++){
    			edge &e=g[u][i];
    			if(e.cap<=e.f)continue;
    			int v=e.to;
    			if(dist[v]==dist[u]+1){
    				ll df=dinic_dfs(v,min(f,e.cap-e.f));
    				if(df>0){e.f+=df;g[v][e.rev].f-=df;return df;}
    			}
    		}
    		return 0;
    	}
    	ll max_flow(int _src, int _dst){
    		src=_src;dst=_dst;
    		ll result=0;
    		while(dinic_bfs()){
    			fill(ALL(work),0);
    			while(ll delta=dinic_dfs(src,INF))result+=delta;
    		}
    		return result;
    	}
    };

    int main(){FIN;
    	int n,m; cin>>n>>m;
    	fore(i,0,n) fore(j,0,n) d[i][j]=INF*(i!=j);
    	fore(i,0,m){
    		int x,y; cin>>x>>y; d[x-1][y-1]=d[y-1][x-1]=1;
    	}
    	fore(k,0,n) fore(i,0,n) fore(j,0,n){
    		if(d[i][k]!=INF&&d[k][j]!=INF) d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
    	}
    	ll ans=0,s,b,k; cin>>s>>b>>k;
    	fore(i,0,s) v[i]=-INF;
    	vector<pair<ii,ii>> a(s);
    	fore(i,0,s) cin>>a[i].fst.fst>>a[i].fst.snd>>a[i].snd.fst>>a[i].snd.snd,a[i].fst.fst--;
    	fore(i,0,b){
    		ll x,di,g; cin>>x>>di>>g; x--; base[x].pb({di,g});
    	}
    	fore(i,0,n){
    		sort(ALL(base[i])); bst[i].resize(SZ(base[i]));
    		fore(j,0,SZ(base[i])){
    			bst[i][j]=base[i][j].snd;
    			if(j) bst[i][j]=max(bst[i][j],bst[i][j-1]);
    		}
    	}
    	Dinic nt(s+2);
    	fore(i,0,SZ(a)){
    		fore(j,0,n){
    			int top=upper_bound(ALL(base[j]),(ii){a[i].fst.snd,INF})-base[j].begin()-1;
    			if(d[a[i].fst.fst][j]<=a[i].snd.fst&&top>=0){
    				v[i]=max(v[i],bst[j][top]-a[i].snd.snd);
    			}
    		}
    		if(v[i]<0) nt.add_edge(i+1,s+1,-v[i]);
    		else ans+=v[i], nt.add_edge(0,i+1,v[i]);
    	}
    	fore(i,0,k){
    		int x,y; cin>>x>>y; nt.add_edge(x,y,INF);
    	}
    	cout << ans-nt.max_flow(0,s+1)<<"\n";
    }

#ifndef OUUAN
#pragma GCC optimize("Ofast,no-stack-protector,unroll-loops,fast-math")
#endif
#include<bits/stdc++.h>

#define int LoveLive
//#define FAST_IOSTREAM 1

#define For(i,l,r)for(int i=(l),i##end=(r);i<=i##end;++i)
#define FOR(i,r,l)for(int i=(r),i##end=(l);i>=i##end;--i)
#define SON(i,u)for(int i=head[u];i;i=nxt[i])
#define ms(a,x)memset(a,x,sizeof(a))
#define fi first
#define se second
#define pq priority_queue
#define pb emplace_back
#define isinf(x)(x>=INF?-1:x)
#define DEBUG(x)cerr<<(#x)<<":"<<x<<endl
using namespace std;typedef long long LoveLive;typedef pair<int,int>pii;typedef vector<int>vi;
#ifdef int
const int INF=0x3f3f3f3f3f3f3f3fll;
#else
const int INF=0x3f3f3f3f;
#endif
const double eps=1e-9;
#ifdef FAST_IOSTREAM
#define br cout<<'\n'
#define sp cout<<' '
template<typename T>void read(T&x){cin>>x;}template<typename T>void write(const T&x){cout<<x;}
#else
#define br putchar('\n')
#define sp putchar(' ')
template<typename T>typename enable_if<!is_integral<T>::value,void>::type read(T&x){cin>>x;}long long
read(){char c;long long out=0,f=1;for(c=getchar();!isdigit(c)&&c!='-';c=getchar());if(c=='-'){f=-1;
c=getchar();}for(;isdigit(c);c=getchar())out=(out<<3)+(out<<1)+c-'0';return out*f;}template<typename
T>typename enable_if<is_integral<T>::value,T>::type read(T&x){char c;T f=1;x=0;for(c=getchar();!isdigit
(c)&&c!='-';c=getchar());if(c=='-'){f=-1;c=getchar();}for(;isdigit(c);c=getchar())x=(x<<3)+(x<<1)+c-'0';
return x*=f;}char read(char&x){for(x=getchar();isspace(x);x=getchar());return x;}double read(double &x)
{scanf("%lf",&x);return x;}void read(char*x){scanf("%s",x);}template<typename T>typename enable_if
<!is_integral<T>::value,void>::type write(const T&x){cout<<x;}template<typename T>typename enable_if
<is_integral<T>::value,void>::type write(const T&x){if(x<0){putchar('-');write(-x);return;}if(x>9)write
(x/10);putchar(x%10+'0');}void write(const char&x){putchar(x);}void write(const double&x){printf
("%.10lf",x);}void write(const char*x){printf("%s",x);}
#endif
template<typename T,typename...Args>void read(T&x,Args&...args){read(x);read(args...);}template<typename
...Args>void read(char*x,Args&...args){read(x);read(args...);}template<typename OutputIt,typename=typename
enable_if<is_same<output_iterator_tag,typename iterator_traits<OutputIt>::iterator_category>::value
||(is_base_of<forward_iterator_tag,typename iterator_traits<OutputIt>::iterator_category>::value&&!
is_const<OutputIt>::value)>::type>void read(OutputIt __first,OutputIt __last){for(;__first!=__last;++
__first)read(*__first);}template<typename InputIt,typename=typename enable_if<is_base_of<input_iterator_tag
,typename iterator_traits<InputIt>::iterator_category>::value>::type>void wts(InputIt __first,InputIt
__last){for(;__first!=__last;++__first){write(*__first);sp;}}template<typename InputIt,typename=typename
enable_if<is_base_of<input_iterator_tag,typename iterator_traits<InputIt>::iterator_category>::value
>::type>void wtb(InputIt __first,InputIt __last){for(;__first!=__last;++__first){write(*__first);br;}}
void wts(const char*x){write(x);sp;}void wtb(const char*x){write(x);br;}template<typename T>void wts
(const T&x){write(x);sp;}template<typename T>void wtb(const T&x){write(x);br;}template<typename...Args
>void wts(const char*x,Args...args){wts(x);wts(args...);}template<typename...Args>void wtb(const char
*x,Args...args){wts(x);wtb(args...);}template<typename T,typename...Args>void wts(const T&x,Args...args
){wts(x);wts(args...);}template<typename T,typename...Args>void wtb(const T&x,Args...args){wts(x);wtb
(args...);}template<typename T>inline bool up(T&x,const T&y){return x<y?x=y,1:0;}template<typename T
>inline bool dn(T&x,const T&y){return y<x?x=y,1:0;}

const int N = 110;
const int K = 1010;
const int S = 100010;
const int mod = 1000000007;

struct Node
{
	int x, a, f, p, type, id;
	bool operator<(const Node & b) const
	{
		return a == b.a ? type > b.type : a < b.a;
	}
} a[S << 1];

queue<int> q;
bool xianzhi[S];
int head[S], cur[S], nxt[K << 4], to[K << 4], edge[K << 4], cnt = 1;
int n, m, c, b, k, ans, mxp[N], g[S], dis[N][N], dep[S], s = S - 2, t = S - 1;

void add(int u, int v, int w)
{
    nxt[++cnt] = head[u];
    head[u] = cnt;
    to[cnt] = v;
    edge[cnt] = w;
}

void Add(int u, int v, int w)
{
	/*DEBUG(u);
	DEBUG(v);
	DEBUG(w);
	cerr << endl;*/
    add(u, v, w);
    add(v, u, 0);
}

int dfs(int u, int flow)
{
    if (dep[u] == dep[t]) return u == t ? flow : 0;
    int v, w, f, out = 0;
    for (int & i = cur[u]; i && flow - out; i = nxt[i])
    {
        v = to[i];
        w = edge[i];
        if (w > 0 && dep[v] == dep[u] + 1)
        {
            f = dfs(v, min(w, flow - out));
            edge[i] -= f;
            edge[i ^ 1] += f;
            out += f;
        }
    }
    return out;
}

bool bfs()
{
    memset(dep, -1, sizeof(dep));
    dep[s] = 0;
    q.push(s);
    while (!q.empty())
    {
        int u = q.front();
        q.pop();
        for (int i = head[u]; i; i = nxt[i])
        {
            int v = to[i];
            int w = edge[i];
            if (w > 0 && dep[v] == -1)
            {
                dep[v] = dep[u] + 1;
                q.push(v);
            }
        }
    }
    return dep[t] > 0;
}

int dinic()
{
    int out = 0;
    while (bfs())
    {
        memcpy(cur, head, sizeof(cur));
        out += dfs(s, INF);
    }
    return out;
}

signed main()
{
#ifdef FAST_IOSTREAM
	cin.sync_with_stdio(false);
	cin.tie(0);
#endif

	read(n, m);

	ms(dis, 0x3f);

	For (i, 1, m)
	{
		int u, v;
		read(u, v);
		dis[u][v] = dis[v][u] = 1;
	}

	For (i, 1, n) dis[i][i] = 0;

	For (k, 1, n) For (i, 1, n) For (j, 1, n) dn(dis[i][j], dis[i][k] + dis[k][j]);

	read(c, b, k);

	For (i, 1, c)
	{
		read(a[i].x, a[i].a, a[i].f, a[i].p);
		a[i].type = 1;
		a[i].id = i;
	}

	For (i, 1, b)
	{
		read(a[i + c].x, a[i + c].a, a[i + c].p);
		a[i + c].type = 2;
	}

	sort (a + 1, a + c + b + 1);

	For (i, 1, n) mxp[i] = -INF;
	For (i, 1, c) g[i] = -INF;

	For (i, 1, c + b)
	{
		if (a[i].type == 1)
		{
			For (j, 1, n) if (dis[a[i].x][j] <= a[i].f) up(g[a[i].id], mxp[j] - a[i].p);
		}
		else up(mxp[a[i].x], a[i].p);
	}

	For (i, 1, k)
	{
		int u, v;
		read(u, v);
		Add(u, v, INF);
		xianzhi[u] = xianzhi[v] = true;
	}

	For (i, 1, c)
	{
		if (xianzhi[i])
		{
			if (g[i] >= 0)
			{
				ans += g[i];
				Add(s, i, g[i]);
			}
			else Add(i, t, -g[i]);
		}
		else if (g[i] > 0) ans += g[i];
	}

	wtb(ans - dinic());

	return 0;
}

#include<bits/stdc++.h>
#define fi first
#define se second
#define pb push_back
#define SZ(x) ((int)x.size())
#define L(i,u) for (register int i=head[u]; i; i=nxt[i])
#define rep(i,a,b) for (register int i=(a); i<=(b); i++)
#define per(i,a,b) for (register int i=(a); i>=(b); i--)
#define int long long
using namespace std;
typedef long long ll;
typedef unsigned int ui;
typedef pair<int,int> Pii;
typedef vector<int> Vi;
template<class T> inline void read(T &x){
	x=0; char c=getchar(); int f=1;
	while (!isdigit(c)) {if (c=='-') f=-1; c=getchar();}
	while (isdigit(c)) {x=x*10+c-'0'; c=getchar();} x*=f;
}
template<class T> inline void umin(T &x, T y){x=x<y?x:y;}
template<class T> inline void umax(T &x, T y){x=x>y?x:y;}
inline ui R() {
	static ui seed=416;
	return seed^=seed>>5,seed^=seed<<17,seed^=seed>>13;
}
const int N = 233220, M = 2030030;
const ll inf = 1e15;
int S,T,head[N],cur[N],nxt[M],cap[M],to[M],edgenum=1; //1.WA£¨ÆäËüµØ·½Ó¦¸Ã¶¼²»ÈÝÒ×Ð´¹Ò£©--edgenum=1!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
void addedge(int u, int v, int c){
	to[++edgenum]=v;cap[edgenum]=c;nxt[edgenum]=head[u];head[u]=edgenum;
}
void add(int u, int v, int c){
	addedge(u,v,c);addedge(v,u,0);
}
int dis[N],q[N];
inline bool bfs() {
	const int inf=0x3f3f3f3f;
	rep(i,0,T)dis[i]=inf;
//	memset(dis,inf,sizeof(int)*(T+2));//2.memset²»ÓÃsizeof()
	int f=0,r=1; q[f]=T; dis[T]=0;
	while (f!=r) {
		int u=q[f++];
		L(i,u) if (cap[i^1]&&dis[to[i]]==inf){
			q[r++]=to[i];dis[to[i]]=dis[u]+1;if(to[i]==S)return 1;//3.¼ôÖ¦
		}
	}
	return dis[S]<inf;
}
inline int dfs(int u, int flow) {
	if (u==T||!flow)return flow;int res=0;
	for(register int &i=cur[u];i;i=nxt[i])if(cap[i]&&dis[u]==dis[to[i]]+1){//4.µ±Ç°»¡
		int tmp=dfs(to[i],min(flow,cap[i]));
		res+=tmp;flow-=tmp;cap[i]-=tmp;cap[i^1]+=tmp;if(!flow)break;
	}
	return res;
}
inline int dinic() {
	int res=0;
	while (bfs()) {
		rep(i,0,T)cur[i]=head[i];
	//	memcpy(cur,head,sizeof(int)*(T+2));
		res+=dfs(S,inf);
	}
	return res;
}
int n,m,ans[233333];
namespace yzr{
	const int N = 233333;
	int dis[111][111],A[N],B[N],C[N],D[N],E[N],F[N];
	Pii s[N];int len,val[N];
	void init(){
		int dot;read(n);read(m);dot=n;
		rep(i,0,n)rep(j,0,n)dis[i][j]=0x3f3f3f3f;
		rep(i,1,n)val[i]=-inf;
		while(m--){
			int u,v;read(u);read(v);
			umin(dis[u][v],1LL);umin(dis[v][u],1LL);
		}
		rep(i,1,n)dis[i][i]=0;
		rep(k,1,n)rep(i,1,n)rep(j,1,n)
			umin(dis[i][j],dis[i][k]+dis[k][j]);
	//	rep(i,1,n){rep(j,1,n)printf("%d ",dis[i][j]);puts("");}
		read(n);int n2;read(n2);read(m);
		rep(i,1,n){
			read(A[i]);read(B[i]);read(C[i]);read(D[i]);ans[i]=-inf;
			s[++len]=Pii(B[i],i);
		}
		rep(i,1,n2){
			int x,d,g;read(x);read(d);read(g);E[i]=x;F[i]=g;
			s[++len]=Pii(d,-i);
		}
		sort(s+1,s+len+1);
		rep(i,1,len)
			if(s[i].se<0){
				umax(val[E[-s[i].se]],F[-s[i].se]);
			}
			else{
				rep(j,1,dot)if(dis[j][A[s[i].se]]<=C[s[i].se])
					umax(ans[s[i].se],val[j]-D[s[i].se]);
			}
	}
}
signed main() {
	yzr::init();
	S=n+1;T=S+1;
	while(m--){
		int u,v;read(u);read(v);add(u,v,inf);
	}
//	rep(i,1,n)cerr<<ans[i]<<' ';cerr<<endl;
	ll res=0;
	rep(i,1,n)
		if(ans[i]>0){res+=ans[i];add(S,i,ans[i]);}
		else{add(i,T,-ans[i]);}
	cout<<res-dinic();
	return 0;
}

#include <bits/stdc++.h>
#define pb push_back
#define fast_cin() ios_base::sync_with_stdio(false); cin.tie(0);
using namespace std;
typedef long double ld;
typedef long long ll;
typedef long long LL;
typedef pair <int, int> pii;
typedef pair <ll, ll> pll;
struct Edge {
  int u, v;
  LL cap, flow;
  Edge() {}
  Edge(int u, int v, LL cap): u(u), v(v), cap(cap), flow(0) {}
};

 /*
 hahaha
 */
struct Dinic {
  int N;
  vector<Edge> E;
  vector<vector<int>> g;
  vector<int> d, pt;

  Dinic(int N): N(N), E(0), g(N), d(N), pt(N) {}

  void AddEdge(int u, int v, LL cap) {
    if (u != v) {
      E.emplace_back(Edge(u, v, cap));
      g[u].emplace_back(E.size() - 1);
      E.emplace_back(Edge(v, u, 0));
      g[v].emplace_back(E.size() - 1);
    }
  }

  bool BFS(int S, int T) {
    queue<int> q({S});
    fill(d.begin(), d.end(), N + 1);
    d[S] = 0;
    while(!q.empty()) {
      int u = q.front(); q.pop();
      if (u == T) break;
      for (int k: g[u]) {
        Edge &e = E[k];
        if (e.flow < e.cap && d[e.v] > d[e.u] + 1) {
          d[e.v] = d[e.u] + 1;
          q.emplace(e.v);
        }
      }
    }
    return d[T] != N + 1;
  }

  LL DFS(int u, int T, LL flow = -1) {
    if (u == T || flow == 0) return flow;
    for (int &i = pt[u]; i < g[u].size(); ++i) {
      Edge &e = E[g[u][i]];
      Edge &oe = E[g[u][i]^1];
      if (d[e.v] == d[e.u] + 1) {
        LL amt = e.cap - e.flow;
        if (flow != -1 && amt > flow) amt = flow;
        if (LL pushed = DFS(e.v, T, amt)) {
          e.flow += pushed;
          oe.flow -= pushed;
          return pushed;
        }
      }
    }
    return 0;
  }

  LL MaxFlow(int S, int T) {
    LL total = 0;
    while (BFS(S, T)) {
      fill(pt.begin(), pt.end(), 0);
      while (LL flow = DFS(S, T))
        total += flow;
    }
    return total;
  }
};

struct ship_t {
	ll x, a, f, p;
};

struct base_t {
	ll x, d, g;
	bool operator<(const base_t &o) const {
		return d < o.d;
	}
};

const int N = 1e2 + 10, S = 1e5 + 10;
const ll inf = 1e12 + 42;

ship_t ship[S];
base_t base[S];
ll g[N][N];
vector<int> dep[S];
vector<pll> bases_at[N];
bool seen[S];
ll val[S];

int main()
{
	fast_cin();
	int n, m;
	cin >> n >> m;
	for (int i = 1; i <= n; ++i) {
		for (int j = i + 1; j <= n; ++j) {
			g[i][j] = g[j][i] = inf;
		}
	}
	for (int i = 0; i < m; ++i) {
		int u, v;
		cin >> u >> v;
		g[u][v] = g[v][u] = min(g[u][v], 1ll);
	}
	for (int k = 1; k <= n; ++k) {
		for (int i = 1; i <= n; ++i) {
			for (int j = 1; j <= n; ++j) {
				g[i][j] = min(g[i][j], g[i][k] + g[k][j]);
			}
		}
	}
	int s, b, k;
	cin >> s >> b >> k;
	for (int i = 1; i <= s; ++i) {
		cin >> ship[i].x >> ship[i].a >> ship[i].f >> ship[i].p;
	}
	for (int i = 1; i <= b; ++i) {
		cin >> base[i].x >> base[i].d >> base[i].g;
	}
	sort(base + 1, base + 1 + b);
	for (int i = 1; i <= b; ++i) {
		int p = base[i].x;
		if (bases_at[p].empty() or bases_at[p].back().second < base[i].g) {
			bases_at[p].pb({base[i].d, base[i].g});
		}
	}
	Dinic dinic(s + 2);
	int source = 0, sink = s + 1;
	ll ans = 0;
	for (int i = 1; i <= s; ++i) {
		bool found = false;
		for (int p = 1; p <= n; ++p) {
			if (g[ship[i].x][p] > ship[i].f) {
				continue;
			}
			auto it = upper_bound(bases_at[p].begin(), bases_at[p].end(), make_pair(ship[i].a, inf));
			if (it != bases_at[p].begin()) {
				--it;
				val[i] = max(val[i], it->second);
				found = true;
			}
		}
		val[i] -= ship[i].p;
		if (!found) {
			val[i] = -inf;
		}
		if (val[i] >= 0) {
			ans += val[i];
			dinic.AddEdge(source, i, val[i]);
		} else {
			dinic.AddEdge(i, sink, -val[i]);
		}
	}
	for (int i = 1; i <= k; ++i) {
		int u, v;
		cin >> u >> v;
		dep[u].pb(v);
	}
	for (int i = 1; i <= s; ++i) {
		if (val[i] < 0) {
			continue;
		}
		vector<int> vis = {i};
		queue<int> q;
		q.push(i);
		seen[i] = true;
		while (!q.empty()) {
			int u = q.front();
			q.pop();
			if (val[u] < 0) {
				dinic.AddEdge(i, u, inf);
			}
			for (auto &v : dep[u]) {
				if (!seen[v]) {
					seen[v] = true;
					vis.pb(v);
					q.push(v);
				}
			}
		}
		for (auto &u : vis) {
			seen[u] = false;
		}
	}
	cout << ans - dinic.MaxFlow(source, sink);
}

#include<bits/stdc++.h>
using namespace std;

typedef long long LL;
typedef long double LD;
typedef pair<int,int> pii;
typedef pair<LL,LL> pll;
const int SZ = 3e6 + 10;
const LL INF = 1e15 + 10;
const int mod = 998244353;
const LD eps = 1e-8;

LL read() {
    LL n = 0;
    char a = getchar();
    bool flag = 0;
    while(a > '9' || a < '0') { if(a == '-') flag = 1; a = getchar(); }
    while(a <= '9' && a >= '0') { n = n * 10 + a - '0',a = getchar(); }
	if(flag) n = -n;
	return n;
}

struct edge {
    int f,t;
    LL d;
}l[SZ];

int head[SZ],nxt[SZ],tot = 1;

void build(int f,int t,LL d) {
    l[++ tot] = (edge){f,t,d};
    nxt[tot] = head[f];
    head[f] = tot;
}

void insert(int f,int t,LL d) {
  //  printf("%d %d %lld\n",f,t,d);
    build(f,t,d); build(t,f,0);
}

int deep[SZ];

bool bfs(int s,int e) {
    for(int i = 1;i <= e;i ++) deep[i] = 0; queue<int> q;
    q.push(s); deep[s] = 1;
    while(q.size()) {
        int u = q.front(); q.pop();
        for(int i = head[u];i;i = nxt[i]) {
            int v = l[i].t;
            if(l[i].d && !deep[v]) {
                deep[v] = deep[u] + 1;
                if(v == e) return true;
                q.push(v);
            }
        }
    }
    return false;
}
LL dfs(int u,LL flow,int e) {
    if(u == e || flow == 0) return flow;
    LL ans = flow;
    for(int i = head[u];i;i = nxt[i]) {
        int v = l[i].t;
        if(l[i].d && deep[v] == deep[u] + 1) {
            LL f = dfs(v,min(ans,l[i].d),e);
            if(f > 0) {
                l[i].d -= f; l[i^1].d += f; ans -= f;
                if(ans == 0) break;
            }
            else deep[v] = 0;
        }
    }
    if(ans == flow) deep[u] = 0;
    return flow - ans;
}
LL dinic(int s,int e) {
    LL ans = 0;
    while(bfs(s,e)) {
        LL tmp = dfs(s,INF,e);
        if(tmp == 0) break;
        ans += tmp;
    }
    return ans;
}

int f[110][110];

struct hhhh {
    int x,a,f,p;
}a[SZ];

vector<pii> base[SZ];
LL val[SZ];
int id[SZ],ff[SZ],tt[SZ],mark[SZ];

int main() {
    int n = read(),m = read();
    memset(f,63,sizeof f);
    for(int i = 1;i <= m;i ++) {
        int x = read(),y = read();
        f[x][y] = f[y][x] = 1;
    }
    for(int k = 1;k <= n;k ++) f[k][k] = 0;
    for(int k = 1;k <= n;k ++)
        for(int i = 1;i <= n;i ++)
            for(int j = 1;j <= n;j ++)
                f[i][j] = min(f[i][j],f[i][k]+f[k][j]);

    int S = read(),B = read(),K = read();
    for(int i = 1;i <= S;i ++) {
        a[i].x = read(),a[i].a = read(),a[i].f = read(),a[i].p = read();
    }
    for(int i = 1;i <= B;i ++) {
        int x = read(),d = read(),g = read();
        base[x].push_back(make_pair(d,g));
    }
    for(int i = 1;i <= n;i ++) {
        sort(base[i].begin(),base[i].end());
        int maxg = -1;
        for(int j = 0;j < base[i].size();j ++) {
            maxg = max(maxg,base[i][j].second);
            base[i][j].second = maxg;
        }
    }

    for(int i = 1;i <= S;i ++) {
        int u = a[i].x;
        LL maxg = -INF;
        for(int v = 1;v <= n;v ++) {
            if(f[u][v] <= a[i].f) {
                auto it = upper_bound(base[v].begin(),base[v].end(),make_pair(a[i].a,(int)(1e9+1)));
                if(it == base[v].begin()) continue;
                it --;
                maxg = max(maxg,1ll * it -> second);
            }
        }
        if(maxg == -INF) val[i] = -1e14;
        else val[i] = maxg - a[i].p;
    }
    for(int i = 1;i <= K;i ++) {
        ff[i] = read(),tt[i] = read();
        mark[ff[i]] = 1;
        mark[tt[i]] = 1;
    }

    LL ans = 0;
   // for(int i = 1;i <= S;i ++) cout << i << " " << val[i] << endl;
    for(int i = 1;i <= S;i ++) if(!mark[i]) ans += max(val[i],0ll);
    int tot = 0;
    for(int i = 1;i <= S;i ++)
        if(mark[i]) {
            id[i] = ++ tot;
        }
 //   cout << tot << endl;
    int s = tot + 1,e = s + 1;
    LL sum = 0;
    for(int i = 1;i <= S;i ++) {
        if(!mark[i]) continue;
        if(val[i] > 0) {
            sum += val[i];
            insert(s,id[i],val[i]);
        }
        else {
            insert(id[i],e,-val[i]);
        }
    }
    for(int i = 1;i <= K;i ++) {
        int x = id[ff[i]],y = id[tt[i]];
        insert(x,y,INF);
    }

    cout << ans + sum - dinic(s,e);

}

#include <bits/stdc++.h>

#define F first
#define S second
#define MP make_pair
#define PB push_back

using namespace std;

typedef long long ll;
typedef long double ld;

const int max_n = 111, inf = 1000111222;
const int max_v = 100011;

namespace flow {

struct edge {
    int v;
    long long res_cap;

    edge() {
    }

    edge(int v, long long res_cap): v(v), res_cap(res_cap) {
    }
};

vector<edge> all;
vector<int> g[max_v];

void add_edge(int u, int v, long long cap) {
    g[u].push_back(all.size());
    all.push_back({v, cap});
    g[v].push_back(all.size());
    all.push_back({u, 0});
}

int h[max_v], num[max_v];

bool bfs(int s, int t) {
    for (int i = 0; i <= t; ++i) {
        h[i] = -1;
    }
    h[s] = 0;
    queue<int> q;
    q.push(s);
    while (!q.empty()) {
        int v = q.front();
        q.pop();
        for (int id : g[v]) {
            if (all[id].res_cap && h[all[id].v] == -1) {
                h[all[id].v] = h[v] + 1;
                q.push(all[id].v);
            }
        }
    }
    return h[t] != -1;
}

int dfs(int v, int t, int f) {
    if (v == t) {
        return f;
    }
    for (int &i = num[v]; i < g[v].size(); ++i) {
        int id = g[v][i];
        const edge &e = all[id];
        if (h[v] + 1 == h[e.v] && e.res_cap) {
            int x = dfs(e.v, t, min(1LL * f, e.res_cap));
            if (x) {
                all[id].res_cap -= x;
                all[id ^ 1].res_cap += x;
                return x;
            }
        }
    }
    return 0;
}

long long dinic(int s, int t) {
    long long res = 0;
    while (bfs(s, t)) {
        memset(num, 0, sizeof(num));
        while (int x = dfs(s, t, 2 * inf)) {
            res += x;
        }
    }
    return res;
}

}

int n, m, dist[max_n][max_n];
int c1, c2, k;
int v1[max_v], attack[max_v], fluel[max_v], cost1[max_v], a[max_v];
int v2[max_v], defend[max_v], cost2[max_v], U[max_v], V[max_v], bad[max_v];
vector<pair<int, int>> all[max_n];
vector<int> rg[max_v];

void dfs(int v) {
    bad[v] = 1;
    for (int to : rg[v]) {
        if (!bad[to]) {
            dfs(to);
        }
    }
}

int main() {
    //freopen("input_b.txt", "r", stdin);
    //freopen("output.txt", "w", stdout);
    scanf("%d%d", &n, &m);
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < n; ++j) {
            dist[i][j] = inf;
        }
        dist[i][i] = 0;
    }
    while (m--) {
        int u, v;
        scanf("%d%d", &u, &v);
        --u;
        --v;
        dist[u][v] = 1;
        dist[v][u] = 1;
    }
    for (int k = 0; k < n; ++k) {
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < n; ++j) {
                dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
            }
        }
    }
    scanf("%d%d%d", &c1, &c2, &k);
    for (int i = 0; i < c1; ++i) {
        scanf("%d%d%d%d", &v1[i], &attack[i], &fluel[i], &cost1[i]);
        --v1[i];
    }
    for (int i = 0; i < c2; ++i) {
        scanf("%d%d%d", &v2[i], &defend[i], &cost2[i]);
        --v2[i];
        all[v2[i]].push_back({defend[i], cost2[i]});
    }
    for (int i = 0; i < n; ++i) {
        sort(all[i].begin(), all[i].end());
        for (int j = 1; j < all[i].size(); ++j) {
            all[i][j].second = max(all[i][j].second, all[i][j - 1].second);
        }
    }
    for (int i = 0; i < c1; ++i) {
        a[i] = -inf;
        for (int v = 0; v < n; ++v) {
            if (dist[v1[i]][v] > fluel[i]) {
                continue;
            }
            auto it = upper_bound(all[v].begin(), all[v].end(), make_pair(attack[i], inf));
            if (it != all[v].begin()) {
                --it;
                a[i] = max(a[i], it->second);
            }
        }
        if (a[i] != -inf) {
            a[i] -= cost1[i];
        } else {
            bad[i] = 1;
        }
        //cout << i << ": " << a[i] << endl;
    }
    int s = c1, t = s + 1;
    long long big_inf = 10001112LL * inf;
    for (int i = 0; i < k; ++i) {
        scanf("%d%d", &U[i], &V[i]);
        --U[i];
        --V[i];
        rg[V[i]].push_back(U[i]);
    }
    for (int i = 0; i < c1; ++i) {
        if (bad[i]) {
            dfs(i);
        }
    }
    long long ans = 0;
    for (int i = 0; i < c1; ++i) {
        if (!bad[i]) {
            flow::add_edge(s, i, inf + a[i]);
            flow::add_edge(i, t, inf);
            ans -= a[i] + inf;
        }
    }
    for (int i = 0; i < k; ++i) {
        if (!bad[U[i]] && !bad[V[i]]) {
            flow::add_edge(U[i], V[i], big_inf);
        }
    }
    ans += flow::dinic(s, t);
    printf("%I64d\n", -ans);
    return 0;
}

#include<bits/stdc++.h>
#define maxn 100005
#define maxm 2005
#define f first
#define s second
#define all(a) a.begin(), a.end()
using namespace std;

typedef long long ll;
ll NINF = -1e18;
ll INF = 1e18;

struct space_ship
{
    int x, a, f, p, stt;
} aa[maxn];

bool operator<(space_ship &a, space_ship &b)
{
    return a.a < b.a;
}

struct base
{
    int x, d, g;
} bb[maxn];

bool operator<(base &a, base &b)
{
    return a.d < b.d;
}

int n, m, s, b, k;

/// DFS

vector< int > P[maxn];

vector< pair<int,int> > e;

/// FLOW

struct edge
{
    int to, rev;
    ll flow, cap;
};

struct PushRelabel
{
    vector< vector< edge > > G;
    vector< edge* > cur;
    vector< ll > ac;
    vector< ll > COUNT;
    vector< ll > h;
    vector< vector< int > > bucket;

    PushRelabel(int n) :
        G(n), cur(n), ac(n), COUNT(2*n), h(n), bucket(2*n) {}

    void add_edge(int s, int t, ll cap)
    {
        if(s == t) return;
        G[s].push_back({t, G[t].size(), 0, cap});
        G[t].push_back({s, G[s].size()-1, 0, 0});
    }

    void add_flow(edge& a, ll f)
    {
        edge& BACK = G[a.to][a.rev];
        if(!ac[a.to] && f) bucket[h[a.to]].push_back(a.to);
        a.flow += f, a.cap -= f, ac[a.to] += f;
        BACK.flow -= f, BACK.cap += f, ac[BACK.to] -= f;
    }

    ll Flow(int s, int t)
    {
        COUNT[0] = t-1;
        COUNT[t] = 1;
        h[s] = t;
        for(int i=1;i<=t;i++) cur[i] = G[i].data();
        for(int i=0;i<G[s].size();i++) add_flow(G[s][i], G[s][i].cap);
        ac[t] = 1;

        int timer = 0;

        for(int hi=0;;)
        {
            ++timer;
            while(bucket[hi].empty())
            {
                if(!hi--)
                {
                    return -ac[s];
                }
            }

            int u = bucket[hi].back();
            bucket[hi].pop_back();

            while(ac[u])
            {
                if(cur[u] == G[u].data() + G[u].size())
                {
                    --COUNT[h[u]];
                    h[u] = 1e9;
                    for(int i=0;i<G[u].size();i++)
                    {
                        auto v = G[u][i];
                        if(v.cap && h[u] > h[v.to] + 1)
                        {
                            h[u] = h[v.to] + 1;
                            cur[u] = &G[u][i];
                        }
                    }
                    ++COUNT[h[u]];
                    if(!COUNT[hi] && hi < t)
                    {
                        for(int i=1;i<=t;i++)
                        {
                            if(hi < h[i] && h[i] < t)
                            {
                                --COUNT[h[i]];
                                h[i] = t+1;
                            }
                        }
                    }
                    hi = h[u];
                }
                else if(cur[u]->cap && h[u] == h[cur[u]->to] + 1)
                {
                    add_flow(*cur[u], min(cur[u]->cap, ac[u]));
                }
                else ++cur[u];
            }
        }
    }
};

ll dist[maxm][maxm];
ll best[maxn], c[maxn];

void Dij(int u, ll *dist)
{
    for(int i=1;i<=n;i++) dist[i] = INF;
    queue< int > Q;
    Q.push(u);
    dist[u] = 0;

    while(Q.size())
    {
        int u = Q.front();
        Q.pop();

        for(auto v : P[u])
        {
            if(dist[v] > dist[u] + 1)
            {
                dist[v] = dist[u] + 1;
                Q.push(v);
            }
        }
    }
}

int main()
{
    //freopen("a.inp","r",stdin);
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)
    {
        int u, v;
        scanf("%d%d",&u,&v);
        if(u == v) continue;
        P[u].push_back(v);
        P[v].push_back(u);
    }
    scanf("%d%d%d",&s,&b,&k);
    for(int i=1;i<=s;i++)
    {
        scanf("%d%d%d%d",&aa[i].x,&aa[i].a,&aa[i].f,&aa[i].p);
        aa[i].stt = i;
    }
    for(int i=1;i<=b;i++)
    {
        scanf("%d%d%d",&bb[i].x,&bb[i].d,&bb[i].g);
    }
    for(int i=1;i<=k;i++)
    {
        int u, v;
        scanf("%d%d",&u,&v);
        e.push_back({u, v});
    }
    for(int i=1;i<=n;i++)
    {
        Dij(i, dist[i]);
        best[i] = NINF;
    }
    int t = 1;
    sort(aa+1,aa+s+1);
    sort(bb+1,bb+b+1);
    ll sum = 0;
    for(int i=1;i<=s;i++)
    {
        while(t <= b && bb[t].d <= aa[i].a)
        {
            best[bb[t].x] = max(best[bb[t].x], (ll)bb[t].g);
            ++t;
        }
        c[aa[i].stt] = NINF;
        for(int j=1;j<=n;j++)
        {
            if(dist[aa[i].x][j] <= aa[i].f && best[j] != NINF)
            {
                c[aa[i].stt] = max(c[aa[i].stt], best[j] - aa[i].p);
            }
        }
        if(c[aa[i].stt] > 0)
        {
            sum = sum + c[aa[i].stt];
        }
    }
    PushRelabel a = PushRelabel(s+3);
    for(int i=0;i<e.size();i++)
    {
        int u = e[i].f;
        int v = e[i].s;
        if(c[u] > 0)
        {
            a.add_edge(s+1,u,c[u]);
            c[u] = 0;
        }
        else if(c[u] < 0)
        {
            a.add_edge(u, s+2, -c[u]);
            c[u] = 0;
        }
        ///
        if(c[v] > 0)
        {
            a.add_edge(s+1,v,c[v]);
            c[v] = 0;
        }
        else if(c[v] < 0)
        {
            a.add_edge(v, s+2, -c[v]);
            c[v] = 0;
        }
        ///
        a.add_edge(u, v, INF);
    }
    cout << sum - a.Flow(s+1, s+2);
}

#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <vector>
#include <iostream>
#include <map>
#include <set>
#include <algorithm>
#include <queue>
#include <sstream>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
#define SZ(x) (int)(x.size())
#define F0(i,n) for(int i=0;i<n;i++)
#define F1(i,n) for(int i=1;i<=n;i++)
#define CL(a,x) memset(x, a, sizeof(x));
#define P(x) cerr << #x << "=" << x << endl

const int inf = 1000002013;
const double pi = atan(1.0)*4.0;
const double eps = 1e-8;
ll gcd(ll x, ll y) { return y ? gcd(y, x%y) : x; }
int bc(int n) { return n ? bc((n-1)&n)+1 : 0; }

const int N = 100001;
int i, j, k, m, n, h;
string s;

int d[101][101];
int attackx[N], attacka[N], attackd[N], attackp[N], profit[N], basen;
vector<pii> bases[N];
int dead[N];
vector<int> depends1[N], depends2[N];

void DFS(int i) {
    if (dead[i]) return;
    dead[i] = 1;
    for (int j : depends2[i]) {
        DFS(j);
    }
}

// Max Flow
// Given: a[][], 0->n
// Result: k
vector<int> adj[2002];
ll a[2002][2002], v[2002], t;

int rec(int i, ll fl) {
    v[i] = 1;
    if (i == t) return 1;
    for (int j : adj[i])
        if (a[i][j]>=fl && !v[j] && rec(j, fl)) {
            a[i][j]-=fl;
            a[j][i]+=fl;
            return 1;
        }
    return 0;
}

ll Flow()
{
    ll ret = 0;
    ll fl = 1e18;
    while (fl) {
        for(i = 0; i <= t; i++) v[i] = 0;
        if (rec(0, fl)) ret += fl; else fl /= 2;
    }
    return ret;
}

void AddEdge(int i, int j, ll f) {
    //cerr << "Add " << i << " " << j << " " << f << endl;
    a[i][j] = f;
    adj[i].push_back(j);
    adj[j].push_back(i);
}

int main() {
    //freopen("x.in", "r", stdin);

    cin >> n >> m;
    F1(i, n) F1(j, n) d[i][j] = (i != j) * inf;
    F1(i, m) {
        cin >> j >> k;
        d[j][k] = d[k][j] = 1;
    }
    F1(k, n) F1(i, n) F1(j, n) d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
    cin >> m >> basen >> k;
    F1(i, m) cin >> attackx[i] >> attacka[i] >> attackd[i] >> attackp[i];
    F1(tt, basen) {
        pii p;
        cin >> i >> p.first >> p.second;
        p.second *= -1;
        bases[i].push_back(p);
    }
    while (k--) {
        int s1, s2;
        cin >> s1 >> s2;
        depends1[s1].push_back(s2);
        depends2[s2].push_back(s1);
    }

    F1(i, n) if (!bases[i].empty()) {
        sort(bases[i].begin(), bases[i].end());
        vector<pii> newbases;
        for (pii& p : bases[i]) {
            p.second *= -1;
            if (newbases.empty()) {
                newbases.push_back(p);
            } else if (p.second > newbases.back().second) newbases.push_back(p);
        }
        bases[i] = newbases;
    }

    F1(i, m) {
        profit[i] = -inf;
        F1(j, n) if (attackd[i] >= d[attackx[i]][j] && !bases[j].empty()) {
            auto it = upper_bound(bases[j].begin(), bases[j].end(), pii(attacka[i], inf));
            if (it != bases[j].begin()) {
                it--;
                profit[i] = max(profit[i], it->second);
            }
        }
    }

    F1(i, m) if (profit[i] < 0) DFS(i);
    ll ans = 0;
    F1(i, m) if (!dead[i] && depends1[i].empty() && depends2[i].empty()) {
        dead[i] = 1;
        if (profit[i] > attackp[i]) ans += profit[i] - attackp[i];
    }

    t = 0;
    map<int, int> M;
    F1(i, m) if (!dead[i]) {
        M[i] = ++t;
        //cerr << i << " " << profit[i] << " " << attackp[i] << endl;
    }
    t++;

    ll pSum = 0, aSum = 0;

    F1(i, m) if (!dead[i]) {
        pSum += profit[i];
        aSum += attackp[i];
        AddEdge(0, M[i], profit[i]);
        AddEdge(M[i], t, attackp[i]);
        for (int j : depends1[i]) if (!dead[j]) {
            AddEdge(M[i], M[j], 1e18);
        }
    }
    ll z = Flow();

    ans += pSum - z;

    cout << ans << endl;

    return 0;
}

#include <bits/stdc++.h>
using namespace std;
const int maxn=112345;
const int inf=0x3f3f3f3f;
const long long INF=0x3f3f3f3f3f3f3f3f;
int n,m,k,dis[105][105],bit[105][maxn],s,b,c[maxn][4],d[maxn][3],s1[1123],s2[1123],best[maxn],S,T,cnt;
bool used[maxn];
map<int,int> mp;
vector<int> def;
inline int ID(int x) {
    return upper_bound(def.begin(),def.end(),x)-def.begin();
}
inline int get(int x) {
    if (mp.find(x)==mp.end()) mp[x]=++cnt;
    return mp[x];
}
inline void update(int x,int val,int *bit) {
    while (x<=m) {
        bit[x]=max(bit[x],val);
        x+=x&-x;
    }
}
inline int query(int x,int *bit) {
    int ret=-inf;
    while (x) {
        ret=max(ret,bit[x]);
        x-=x&-x;
    }
    return ret;
}
struct edge {
    int to;
    long long cap;
    int rev;
    edge(){}
    edge(int to,long long cap,int rev):to(to),cap(cap),rev(rev){}
};
vector<edge> G[2123];
int level[2123],iter[2123];
inline void addedge(int from,int to,long long cap) {
    G[from].push_back(edge(to,cap,G[to].size()));
    G[to].push_back(edge(from,0,G[from].size()-1));
}
inline void bfs(int s) {
    memset(level,-1,sizeof level);
    queue<int> que;
    level[s]=0;
    que.push(s);
    while (!que.empty()) {
        int v=que.front();
        que.pop();
        for (int i=0;i<(int)G[v].size();++i) {
            edge &e=G[v][i];
            if (e.cap>0&&level[e.to]<0) {
                level[e.to]=level[v]+1;
                que.push(e.to);
            }
        }
    }
}
long long dfs(int v,int t,long long f) {
    if (v==t) return f;
    for (int &i=iter[v];i<(int)G[v].size();++i) {
        edge &e=G[v][i];
        if (e.cap>0&&level[v]<level[e.to]) {
            long long d=dfs(e.to,t,min(f,e.cap));
            if (d>0) {
                e.cap-=d;
                G[e.to][e.rev].cap+=d;
                return d;
            }
        }
    }
    return 0;
}
inline long long max_flow(int s,int t) {
    long long flow=0;
    while (1) {
        bfs(s);
        if (level[t]<0) return flow;
        memset(iter,0,sizeof iter);
        int f;
        while ((f=dfs(s,t,INF))>0) flow+=f;
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    memset(dis,0x3f,sizeof dis);
    for (int i=1;i<=n;++i) dis[i][i]=0;
    for (int i=1;i<=m;++i) {
        int u,v;scanf("%d%d",&u,&v);
        dis[u][v]=dis[v][u]=1;
    }
    for (int k=1;k<=n;++k)
        for (int i=1;i<=n;++i)
            for (int j=1;j<=n;++j)
                dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
    scanf("%d%d%d",&s,&b,&k);
    for (int i=1;i<=s;++i) for (int j=0;j<4;++j) scanf("%d",&c[i][j]);
    for (int i=1;i<=b;++i) for (int j=0;j<3;++j) scanf("%d",&d[i][j]),def.push_back(d[i][1]);
    for (int i=1;i<=k;++i) scanf("%d%d",&s1[i],&s2[i]),used[s1[i]]=used[s2[i]]=true;
    sort(def.begin(),def.end());
    def.erase(unique(def.begin(),def.end()),def.end());
    m=def.size();
    for (int i=1;i<=n;++i) for (int j=1;j<=m;++j) bit[i][j]=-inf;
    for (int i=1;i<=b;++i) update(ID(d[i][1]),d[i][2],bit[d[i][0]]);
    for (int i=1;i<=s;++i) {
        best[i]=-inf;
        for (int j=1;j<=n;++j) if (dis[c[i][0]][j]<=c[i][2]) best[i]=max(best[i],query(ID(c[i][1]),bit[j]));
    }
    for (int i=1;i<=s;++i) if (best[i]!=-inf) best[i]-=c[i][3];
    long long res=0;
    S=0,T=2001;
    for (int i=1;i<=s;++i) if (!used[i]) res+=max(0,best[i]);
    else {
        if (best[i]>=0) addedge(S,get(i),best[i]),res+=best[i];
        else if (best[i]==-inf) addedge(get(i),T,INF);
        else addedge(get(i),T,-best[i]);
    }
    for (int i=1;i<=k;++i) addedge(get(s1[i]),get(s2[i]),INF);
    res-=max_flow(S,T);
    cout<<res<<endl;
    return 0;
}

#include <bits/stdc++.h>
using namespace std;
int n, m;
int tav[109][109];
int s, b, KK;
long long legjobb[109][109]; // csucs, tav
long long profit[100009];
long long infi=1e18;
struct BaseShip
{
    int lo;
    int pwr;
    int fuel;
    int cost;
    int tp;
    int idx;
    bool operator<(const BaseShip & BS) const
    {
        if(pwr==BS.pwr)
        {
            return tp<BS.tp;
        }
        return pwr<BS.pwr;
    }
};
vector<BaseShip> t;
void javit(BaseShip & BS)
{
    for(int i=1; i<=n; i++)
    {
        if(tav[i][BS.lo]>=0)
        {
            legjobb[i][tav[i][BS.lo]]=max(legjobb[i][tav[i][BS.lo]], (long long)BS.cost);
        }
    }
}
long long ertek(BaseShip & BS)
{
    //cout<<BS.idx<<" start:"<<endl;
    long long ret=-infi;
    //cout<<"ret: "<<ret<<endl;
    for(int dd=0; dd<=min(n-1, BS.fuel); dd++)
    {
        //cout<<"legjobb "<<BS.lo<<" "<<dd<<" = "<<(long long)legjobb[BS.lo][dd]<<endl;
        ret=max(ret, (long long)legjobb[BS.lo][dd]);
        //cout<<"ret: "<<ret<<endl;
    }
    return ret;
}
vector<int> G[100009];
vector<long long> cap[100009];
vector<long long> flow[100009];
vector<int> holvan[100009];
int bejar[100009];
int bejarszam;
int apa[100009];
int apael[100009];
long long profitsum=0;
int sor[100009];
long long FF()
{
    long long ret=0;
    int start=0;
    int sk;
    int sv;
    while(1)
    {
        sk=1;
        sv=1;
        sor[1]=start;
        bejarszam++;
        bejar[start]=bejarszam;
        apa[start]=-1;
        apael[start]=-1;
        while(sk<=sv)
        {
            int akt=sor[sk];
            for(int i=0; i<G[akt].size(); i++)
            {
                int sz=G[akt][i];
                long long cc=cap[akt][i];
                if(bejar[sz]==bejarszam) continue;
                if(cc==flow[akt][i]) continue;
                sv++;
                sor[sv]=sz;
                apa[sz]=akt;
                apael[sz]=i;
                bejar[sz]=bejarszam;
            }
            sk++;
        }
        if(bejar[s+1]<bejarszam) break;
        long long maxpush=infi;
        int akt=s+1;
        while(akt!=0)
        {
            if(cap[apa[akt]][apael[akt]]==0)
            {
                maxpush=min(maxpush, flow[apa[akt]][apael[akt]]);
            }
            else
            {
                maxpush=min(maxpush, cap[apa[akt]][apael[akt]]-flow[apa[akt]][apael[akt]]);
            }
            //cout<<akt<<"->";
            akt=apa[akt];
        }
        //cout<<endl;
        akt=s+1;
        while(akt!=0)
        {
            //at kell irni a folyamot
            if(cap[apa[akt]][apael[akt]]==0)
            {
                flow[apa[akt]][apael[akt]]-=maxpush;
                flow[akt][holvan[apa[akt]][apael[akt]]]-=maxpush;
            }
            else
            {
                flow[apa[akt]][apael[akt]]+=maxpush;
                flow[akt][holvan[apa[akt]][apael[akt]]]+=maxpush;
            }
            akt=apa[akt];
        }
        ret+=maxpush;
    }
    return ret;
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cin>>n>>m;
    for(int i=1; i<=n; i++)
    {
        for(int j=1; j<=n; j++)
        {
            tav[i][j]=-1;
        }
        tav[i][i]=0;
    }
    for(int i=1; i<=m; i++)
    {
        int a, b;
        cin>>a>>b;
        if(a!=b)
        {
            tav[a][b]=1;
            tav[b][a]=1;
        }
    }
    for(int k=1; k<=n; k++)
    {
        for(int i=1; i<=n; i++)
        {
            for(int j=1; j<=n; j++)
            {
                if(tav[i][k]>=0 && tav[k][j]>=0)
                {
                    if(tav[i][j]==-1 || tav[i][j]>tav[i][k]+tav[k][j]) tav[i][j]=tav[i][k]+tav[k][j];
                }
            }
        }
    }
    for(int i=1; i<=n; i++)
    {
        for(int j=0; j<=n; j++)
        {
            legjobb[i][j]=-infi;
        }
    }
    cin>>s>>b>>KK;
    t.resize(s+b);
    for(int i=0; i<s; i++)
    {
        cin>>t[i].lo>>t[i].pwr>>t[i].fuel>>t[i].cost;
        t[i].tp=1;
        t[i].idx=i+1;
    }
    for(int i=s; i<s+b; i++)
    {
        cin>>t[i].lo>>t[i].pwr>>t[i].cost;
        t[i].tp=0;
    }
    sort(t.begin(), t.end());
    for(int i=0; i<t.size(); i++)
    {
        //cout<<"5_0: "<<legjobb[5][0]<<endl;
        if(t[i].tp==0)
        {
            javit(t[i]);
        }
        else
        {
            profit[t[i].idx]=ertek(t[i])-t[i].cost;
            //cout<<t[i].idx<<" profit: "<<profit[t[i].idx]<<endl;
            if(profit[t[i].idx]>=0)
            {
                profitsum+=profit[t[i].idx];
            }
        }
    }
    for(int i=1; i<=KK; i++)
    {
        int s1, s2;
        cin>>s1>>s2;
        if(s1==s2) continue;
        holvan[s1].push_back(G[s2].size());
        holvan[s2].push_back(G[s1].size());
        G[s1].push_back(s2);
        G[s2].push_back(s1);
        cap[s1].push_back(infi);
        cap[s2].push_back(0);
        flow[s1].push_back(0);
        flow[s2].push_back(0);
    }
    for(int i=1; i<=s; i++)
    {
        if(G[i].size()==0) continue;
        if(profit[i]>=0)
        {
            holvan[0].push_back(G[i].size());
            holvan[i].push_back(G[0].size());
            G[0].push_back(i);
            G[i].push_back(0);
            cap[0].push_back(profit[i]);
            cap[i].push_back(0);
            flow[0].push_back(0);
            flow[i].push_back(0);
        }
        else
        {
            holvan[s+1].push_back(G[i].size());
            holvan[i].push_back(G[s+1].size());
            G[s+1].push_back(i);
            G[i].push_back(s+1);
            cap[s+1].push_back(0);
            cap[i].push_back(-profit[i]);
            flow[s+1].push_back(0);
            flow[i].push_back(0);
        }
    }
    /*for(int i=1; i<=s; i++)
    {
        cout<<profit[i]<<" --profit"<<endl;
    }
    for(int i=0; i<=s+1; i++)
    {
        for(int j=0; j<G[i].size(); j++)
        {
            int sz=G[i][j];
            cout<<i<<" --- "<<sz<<" cap: "<<cap[i][j]<<" folyam: "<<flow[i][j]<<endl;
        }
    }*/
    long long mincut=FF();
    //cout<<"mincut: "<<mincut<<endl;
    cout<<profitsum-mincut<<endl;
    return 0;
}

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

#ifdef iq
  mt19937 rnd(228);
#else
  mt19937 rnd(chrono::high_resolution_clock::now().time_since_epoch().count());
#endif

const int N = (int) (1e5) + 7;

vector <int> gr[N];
vector <int> ingr[N];

vector <pair <int, int> > guys[N];
vector <int> pref[N];

const int MAXN = 1e5; // число вершин
const int INF = 1000000007; // константа-бесконечность

struct edge {
	int a, b, cap, flow;
};

int n, s, t, d[MAXN], ptr[MAXN], q[MAXN];
vector<edge> e;
vector<int> g[MAXN];

void add_edge (int a, int b, int cap) {
	edge e1 = { a, b, cap, 0 };
	edge e2 = { b, a, 0, 0 };
	g[a].push_back ((int) e.size());
	e.push_back (e1);
	g[b].push_back ((int) e.size());
	e.push_back (e2);
}

bool bfs() {
	int qh=0, qt=0;
	q[qt++] = s;
	memset (d, -1, n * sizeof d[0]);
	d[s] = 0;
	while (qh < qt && d[t] == -1) {
		int v = q[qh++];
		for (size_t i=0; i<g[v].size(); ++i) {
			int id = g[v][i],
				to = e[id].b;
			if (d[to] == -1 && e[id].flow < e[id].cap) {
				q[qt++] = to;
				d[to] = d[v] + 1;
			}
		}
	}
	return d[t] != -1;
}

int dfs (int v, int flow) {
	if (!flow)  return 0;
	if (v == t)  return flow;
	for (; ptr[v]<(int)g[v].size(); ++ptr[v]) {
		int id = g[v][ptr[v]],
			to = e[id].b;
		if (d[to] != d[v] + 1)  continue;
		int pushed = dfs (to, min (flow, e[id].cap - e[id].flow));
		if (pushed) {
			e[id].flow += pushed;
			e[id^1].flow -= pushed;
			return pushed;
		}
	}
	return 0;
}

ll dinic() {
	ll flow = 0;
	for (;;) {
		if (!bfs())  break;
		memset (ptr, 0, n * sizeof ptr[0]);
		while (int pushed = dfs (s, INF))
			flow += pushed;
	}
	return flow;
}

int main() {
#ifdef iq
  freopen("a.in", "r", stdin);
#endif
  ios::sync_with_stdio(0);
  cin.tie(0);
  ll ans = 0;
  vector <int> id;
  vector <int> cost;
  vector <pair <int, int> > go;
  {
    int n, m;
    cin >> n >> m;
    int inf = (int) (1e9) + 7;
    vector <vector <int> > g(n, vector <int> (n, inf));
    for (int i = 0; i < n; i++) g[i][i] = 0;
    for (int i = 0; i < m; i++) {
      int a, b;
      cin >> a >> b;
      a--, b--;
      g[a][b] = g[b][a] = 1;
    }
    for (int k = 0; k < n; k++) {
      for (int i= 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
          g[i][j] = min(g[i][j], g[i][k] + g[k][j]);
        }
      }
    }
    int s, b, k;
    cin >> s >> b >> k;
    vector <int> x(s), a(s), f(s), p(s);
    for (int i = 0; i < s; i++) {
      cin >> x[i] >> a[i] >> f[i] >> p[i];
      x[i]--;
    }
    vector <int> y(b), d(b), gold(b);
    for (int i = 0; i < b; i++) {
      cin >> y[i] >> d[i] >> gold[i];
      y[i]--;
      guys[y[i]].push_back({d[i], gold[i]});
    }
    for (int i = 0; i < n; i++) {
      sort(guys[i].begin(), guys[i].end());
      pref[i].resize(guys[i].size());
      for (int j = 0; j < (int) pref[i].size(); j++) {
        pref[i][j] = guys[i][j].second;
        if (j) pref[i][j] = max(pref[i][j], pref[i][j - 1]);
      }
    }
    vector <bool> alive(s);
    vector <int> score(s);
    for (int i = 0; i < s; i++) {
      vector <int> ok;
      for (int j = 0; j < n; j++) {
        if (g[x[i]][j] <= f[i]) {
          int ind = upper_bound(guys[j].begin(), guys[j].end(), make_pair(a[i], inf)) - guys[j].begin() - 1;
          if (ind >= 0) {
            ok.push_back(pref[j][ind]);
          }
        }
      }
      if (!ok.empty()) {
        score[i] = *max_element(ok.begin(), ok.end()) - p[i];
        alive[i] = true;
      }
    }
    vector <bool> in_edge(s);
    vector <pair <int, int> > edges;
    for (int i = 0; i < k; i++) {
      int u, v;
      cin >> u >> v;
      u--, v--;
      in_edge[u] = in_edge[v] = true;
      edges.push_back({u, v});
    }
    bool ch = true;
    while (ch) {
      ch = false;
      for (auto c : edges) {
        if (!alive[c.second] && alive[c.first]) {
          ch = true;
          alive[c.first] = false;
        }
      }
    }
    for (int i = 0; i < s; i++) {
      if (!in_edge[i]) {
        ans += max(0, score[i]);
      }
    }
    for (int i = 0; i < s; i++) {
      if (in_edge[i] && alive[i]) {
        id.push_back(i);
        cost.push_back(score[i]);
      }
    }
    for (auto c : edges) {
      if (!alive[c.first] || !alive[c.second]) {
        continue;
      }
      int u = lower_bound(id.begin(), id.end(), c.first) - id.begin();
      int v = lower_bound(id.begin(), id.end(), c.second) - id.begin();
      go.push_back({u, v});
    }
  }
  n = 2 + id.size();
  s = id.size();
  t = id.size() + 1;
  for (auto c : go) {
    add_edge(c.first, c.second, INF);
  }
  for (int i= 0; i < (int) id.size(); i++) {
    if (cost[i] >= 0) {
      ans += cost[i];
      add_edge(s, i, cost[i]);
    } else {
      add_edge(i, t, -cost[i]);
    }
  }
  cout << ans - dinic() << '\n';
}

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

template<typename T> struct Dinic {
	static const int MAXN = 100005, MAXM = 1000005;
	struct Edge { int to, next; T cap; } edge[MAXM];
	int head[MAXN], tot;
	void clear() { memset(head, -1, sizeof(head)); tot = 0; }
	Dinic() { clear(); }
	void add(int u, int v, T c) {
		edge[tot] = (Edge) { v, head[u], c };
		head[u] = tot++;
		edge[tot] = (Edge) { u, head[v], (T)0 };
		head[v] = tot++;
	}
	int dis[MAXN], que[MAXN], id[MAXN];
	bool bfs(int s, int t) {
		memset(dis, -1, sizeof(dis));
		memcpy(id, head, sizeof(id));
		int he = 0, ta = 0;
		dis[que[ta++] = s] = 0;
		while (he < ta) {
			int u = que[he++];
			for (int i = head[u]; ~i; i = edge[i].next) {
				int v = edge[i].to;
				if (dis[v] < 0 && edge[i].cap) {
					dis[que[ta++] = v] = dis[u] + 1;
					if (v == t) return true;
				}
			}
		}
		return false;
	}
	T dfs(int u, int t, T f) {
		if (u == t) return f;
		T flow = 0;
		for (int &i = id[u]; ~i; i = edge[i].next) {
			int v = edge[i].to;
			if (dis[v] > dis[u] && edge[i].cap) {
				int d = dfs(v, t, min(f, edge[i].cap));
				if (!d) continue;
				edge[i].cap -= d, edge[i ^ 1].cap += d;
				flow += d, f -= d;
				if (f == 0) return flow;
			}
		}
		dis[u] = -1; return flow;
	}
	T dinic(int s, int t, T inf = 1E9) {
		T flow = 0;
		while (bfs(s, t))
			flow += dfs(s, t, inf);
		return flow;
	}
};
const ll INF = 1E15;
Dinic<ll> din;
const int MAXN = 100005;
int dis[105][105], xx[MAXN], aa[MAXN], ff[MAXN], pp[MAXN], qq[MAXN], vis[MAXN], n, m;
struct Node { int d, g; } sh[MAXN];
vector<Node> nd[105];
bool cmp(const Node &a, const Node &b) { return a.d < b.d; }
int main() {
	scanf("%d%d", &n, &m);
	memset(dis, 0x3f, sizeof(dis));
	for (int i = 1; i <= n; i++) dis[i][i] = 0;
	for (int i = 1; i <= m; i++) {
		int u, v; scanf("%d%d", &u, &v);
		dis[u][v] = dis[v][u] = 1;
	}
	for (int i = 1; i <= n; i++)
	for (int j = 1; j <= n; j++)
	for (int k = 1; k <= n; k++)
		dis[j][k] = min(dis[i][j] + dis[i][k], dis[j][k]);
	int S, B, K; scanf("%d%d%d", &S, &B, &K);
	for (int i = 1; i <= S; i++) {
		scanf("%d%d%d%d", xx + i, aa + i, ff + i, pp + i);
		sh[i] = (Node) { aa[i], i };
	}
	sort(sh + 1, sh + 1 + S, cmp);
	for (int i = 1; i <= B; i++) {
		int x, d, g; scanf("%d%d%d", &x, &d, &g);
		nd[x].push_back((Node) { d, g });
	}
	for (int i = 1; i <= n; i++) {
		sort(nd[i].begin(), nd[i].end(), cmp);
		int mx = 0;
		for (Node &d : nd[i]) {
			mx = max(mx, d.g);
			d.g = mx;
		}
	}
	fill(qq + 1, qq + 1 + S, -1E9);
	for (int i = 1; i <= n; i++) {
		int s = nd[i].size();
		for (int j = 1, k = 0; j <= S; j++) {
			for (; k < s && nd[i][k].d <= sh[j].d; ++k);
			if (k > 0 && dis[i][xx[sh[j].g]] <= ff[sh[j].g])
				qq[sh[j].g] = max(qq[sh[j].g], nd[i][k - 1].g);
		}
	}
	for (int i = 1; i <= S; i++) pp[i] = qq[i] - pp[i];
	for (int i = 1; i <= K; i++) {
		int u, v; scanf("%d%d", &u, &v);
		din.add(u, v, INF);
		vis[u] = vis[v] = 1;
	}
	ll ans = 0;
	int s = S + 1, t = s + 1;
	for (int i = 1; i <= S; i++) if (!vis[i] && pp[i] > 0) ans += pp[i];
	for (int i = 1; i <= S; i++) if (vis[i]) {
		if (pp[i] > 0) din.add(s, i, pp[i]), ans += pp[i];
		else din.add(i, t, -pp[i]);
	}
	printf("%lld\n", ans - din.dinic(s, t, INF));
	return 0;
}

#include <bits/stdc++.h>
#define Inf 1e18
#define M 2000010
#define PLL pair <ll, ll>
#define x first
#define y second

using namespace std;

typedef long long ll;

int Head[M], Next[M], Go[M], Cnt = 0;

struct flow {
	int Head[250010], Next[M], Go[M], Cnt;
	ll Val[M], Fl[250010];
	int Am[250010], H[250010], Pr[250010], Nw[250010];
	flow() {Cnt = 1, memset(Head, 0, sizeof Head);}
	void addedge(int a, int b, ll c) {
		Go[++Cnt] = b;
		Next[Cnt] = Head[a];
		Head[a] = Cnt;
		Val[Cnt] = c;
	}
	ll getflow(int S, int TT, int tot) {
		int x = S;
		ll f = Inf;
		Am[0] = tot;
		ll ans = 0;
		while(H[x] <= tot) {
			if(!Nw[x]) Nw[x] = Head[x];
			int flag = 0;
			for(int &T = Nw[x]; T; T = Next[T])
				if(Val[T] && H[Go[T]] == H[x] - 1) {
					flag = 1, Pr[Go[T]] = T ^ 1;
					Fl[x] = f, f = min(f, Val[T]);
					x = Go[T];
					if(x == TT) {
						ans += f;
						while(x != S) Val[Pr[x]] += f, Val[Pr[x] ^ 1] -= f, x = Go[Pr[x]];
						f = Inf; //!!!
					}
					break; //!!!
				}
			if(!flag) {
				int mn = tot;
				for(int T = Head[x]; T; T = Next[T]) if(Val[T] && H[Go[T]] < mn) mn = H[Go[T]], Nw[x] = T;
				if(!--Am[H[x]]) break;
				Am[H[x] = mn + 1]++;
				if(x != S) {
					x = Go[Pr[x]];
					f = Fl[x];
				}
			}
		}
		return ans;
	}
} qwq;

int n, m, Dis[105][105], XA[250010], AA[250010], FA[250010], PA[250010], XB[250010], DB[250010], GB[250010];

ll Ans[100010];

vector <PLL> V[105];

int main() {
	scanf("%d%d", &n, &m);
	memset(Dis, 63, sizeof Dis);
	for(int i = 1; i <= n; i++) Dis[i][i] = 0;
	for(int i = 1; i <= m; i++) {
		int a, b;
		scanf("%d%d", &a, &b);
		Dis[a][b] = 1, Dis[b][a] = 1;
	}
	for(int i = 1; i <= n; i++)
		for(int j = 1; j <= n; j++)
			for(int k = 1; k <= n; k++) Dis[j][k] = min(Dis[j][k], Dis[j][i] + Dis[i][k]);
	int s, b, k;
	scanf("%d%d%d", &s, &b, &k);
	for(int i = 1; i <= s; i++) scanf("%d%d%d%d", &XA[i], &AA[i], &FA[i], &PA[i]);
	for(int i = 1; i <= n; i++) V[i].push_back(PLL(-1e18, -1e18));
	for(int i = 1; i <= b; i++) {
		int x, d, g;
		scanf("%d%d%d", &x, &d, &g);
		V[x].push_back(PLL(d, g));
	}
	for(int i = 1; i <= n; i++) {
		sort(V[i].begin(), V[i].end());
		for(int j = 1; j < V[i].size(); j++) V[i][j].y = max(V[i][j].y, V[i][j - 1].y);
	}
	for(int i = 1; i <= s; i++) {
		ll ans = -1e18; // notice PA
		for(int j = 1; j <= n; j++) if(Dis[XA[i]][j] <= FA[i])
			ans = max(ans, V[j][lower_bound(V[j].begin(), V[j].end(), PLL(AA[i] + 1, -Inf)) - V[j].begin() - 1].y);
		Ans[i] = ans - PA[i];
	}
	while(k--) {
		int s1, s2;
		scanf("%d%d", &s1, &s2);
		qwq.addedge(s1, s2, Inf);
		qwq.addedge(s2, s1, 0);
	}
	ll ans = 0;
	for(int i = 1; i <= s; i++) if(Ans[i] > 0) ans += Ans[i], qwq.addedge(s + 1, i, Ans[i]), qwq.addedge(i, s + 1, 0); else qwq.addedge(i, s + 2, -Ans[i]), qwq.addedge(s + 2, i, 0);
	printf("%lld\n", ans - qwq.getflow(s + 1, s + 2, s + 2));
	return 0;
}

#include <bits/stdc++.h>

using namespace std;

const int inf = 1e9 + 7;
const long long infll = 1e18;

struct Edge {
  int from, to, index;
  long long cap, flow;
  Edge(int from, int to, long long cap, long long flow, int index) :
  from(from), to(to), index(index), cap(cap), flow(flow) {}
};

struct Dinic {
  int N;
  vector<vector<Edge> > G;
  vector<Edge *> dad;
  vector<int> Q;

  Dinic(int N) : N(N), G(N), dad(N), Q(N) {}

  void AddEdge(int from, int to, long long cap) {
    G[from].push_back(Edge(from, to, cap, 0LL, G[to].size()));
    if (from == to) G[from].back().index++;
    G[to].push_back(Edge(to, from, 0, 0, G[from].size() - 1));
  }

  long long BlockingFlow(int s, int t) {
    fill(dad.begin(), dad.end(), (Edge *) NULL);
    dad[s] = &G[0][0] - 1;

    int head = 0, tail = 0;
    Q[tail++] = s;
    while (head < tail) {
      int x = Q[head++];
      for (int i = 0; i < G[x].size(); i++) {
        Edge &e = G[x][i];
        if (!dad[e.to] && e.cap - e.flow > 0) {
          dad[e.to] = &G[x][i];
          Q[tail++] = e.to;
        }
      }
    }
    if (!dad[t]) return 0;

    long long totflow = 0;
    for (int i = 0; i < G[t].size(); i++) {
      Edge *start = &G[G[t][i].to][G[t][i].index];
      long long amt = infll;
      for (Edge *e = start; amt && e != dad[s]; e = dad[e->from]) {
        if (!e) { amt = 0; break; }
        amt = min(amt, e->cap - e->flow);
      }
      if (amt == 0) continue;
      for (Edge *e = start; amt && e != dad[s]; e = dad[e->from]) {
        e->flow += amt;
        G[e->to][e->index].flow -= amt;
      }
      totflow += amt;
    }
    return totflow;
  }

  long long GetMaxFlow(int s, int t) {
    long long totflow = 0;
    while (long long flow = BlockingFlow(s, t))
      totflow += flow;
    return totflow;
  }
};

const int N = 1e5 + 5;

int dist[111][111];
struct Ship {
  int x, a, f, p;
} ships[N];

int best[111];
int num[N];

int main() {
  int n, m;
  scanf("%d %d", &n, &m);
  for (int i = 1; i <= n; ++i) {
    for (int j = 1; j <= n; ++j)
      dist[i][j] = inf;
    dist[i][i] = 0;
  }
  for (int i = 0; i < m; ++i) {
    int u, v;
    scanf("%d %d", &u, &v);
    dist[u][v] = dist[v][u] = min(dist[u][v], 1);
  }
  for (int k = 1; k <= n; ++k)
    for (int i = 1; i <= n; ++i)
      for (int j = 1; j <= n; ++j)
        dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
  int s, b, k;
  scanf("%d %d %d", &s, &b, &k);
  vector<pair<int, int>> spaces(s);
  for (int i = 0; i < s; ++i) {
    int x, a, f, p;
    scanf("%d %d %d %d", &x, &a, &f, &p);
    ships[i] = {x, a, f, p};
    spaces[i] = make_pair(a, i);
  }
  vector<tuple<int, int, int>> bases(b);
  for (int i = 0; i < b; ++i) {
    int x, d, g;
    scanf("%d %d %d", &x, &d, &g);
    bases[i] = make_tuple(d, x, g);
  }
  sort(spaces.begin(), spaces.end());
  sort(bases.begin(), bases.end());
  memset(best, -1, sizeof best);
  for (int i = 0, j = 0; i < s; ++i) {
    int now = spaces[i].second;
    while (j < (int)bases.size() && get<0>(bases[j]) <= spaces[i].first) {
      int x, g;
      tie(ignore, x, g) = bases[j];
      ++j;
      best[x] = max(best[x], g);
    }
    int cur = -1;
    for (int j = 1; j <= n; ++j) {
      if (dist[ships[now].x][j] > ships[now].f) continue;
      cur = max(cur, best[j]);
    }
    if (cur < 0)
      ships[now].p = -inf;
    else
      ships[now].p = cur - ships[now].p;
  }
  vector<pair<int, int>> cons(k);
  vector<int> nodes;
  for (int i = 0; i < k; ++i) {
    int u, v;
    scanf("%d %d", &u, &v);
    --u, --v;
    cons[i] = make_pair(u, v);
    nodes.push_back(u);
    nodes.push_back(v);
  }
  sort(nodes.begin(), nodes.end());
  nodes.erase(unique(nodes.begin(), nodes.end()), nodes.end());
  Dinic mf((int)nodes.size() + 2);
  int st = nodes.size(), en = st + 1;
  long long tot = 0;
  for (int i = 0; i < s; ++i) {
    if (ships[i].p > 0) {
      tot += ships[i].p;
    }
    int v = lower_bound(nodes.begin(), nodes.end(), i) - nodes.begin();
    if (v == (int)nodes.size() || nodes[v] != i)
      continue;
    if (ships[i].p > 0) {
      mf.AddEdge(st, v, ships[i].p);
    }
    else if (ships[i].p <= -inf) {
      mf.AddEdge(v, en, infll);
    }
    else {
      mf.AddEdge(v, en, -ships[i].p);
    }
  }
  for (auto it : cons) {
    int u = it.first, v = it.second;
    u = lower_bound(nodes.begin(), nodes.end(), u) - nodes.begin();
    v = lower_bound(nodes.begin(), nodes.end(), v) - nodes.begin();
    mf.AddEdge(u, v, inf);
  }
  tot -= mf.GetMaxFlow(st, en);
  printf("%lld\n", tot);
  return 0;
}

#include "bits/stdc++.h"
using namespace std;
int adj[111][111];
int xp[100010], a[100010], f[100010], p[100010];
int xb[100010], d[100010], g[100010];

const long long inf = 1e17;
long long opt[111];
long long profit[100010];
const long long max_profit = 1000000000;

struct MaxFlow {
	#define int long long
	#define MAX_N 100010
	#define INF inf
	typedef long long lld;

	struct Node
	{
	    vector<int> adj;
	};
	Node graf[MAX_N];

	struct Edge
	{
	    int u, v, cap;
	    int flow;
	};
	vector<Edge> E;

	int v;
	int s, t;
	int dist[MAX_N];
	int upTo[MAX_N];

	int idd = 0;

	//Dinicov algoritam za nalazenje maksimalnog protoka izmedju dva cvora u grafu
	//Slozenost: O(V^2 * E)

	inline bool BFS()
	{
	    for (int i=1;i<=v;i++) dist[i] = -1;
	    queue<int> bfs_queue;
	    bfs_queue.push(s);
	    dist[s] = 0;
	    while (!bfs_queue.empty())
	    {
	        int xt = bfs_queue.front();
	        bfs_queue.pop();
	        for (int i=0;i<graf[xt].adj.size();i++)
	        {
	            int currID = graf[xt].adj[i];
	            int xt1 = E[currID].v;
	            if (dist[xt1] == -1 && E[currID].flow < E[currID].cap)
	            {
	                bfs_queue.push(xt1);
	                dist[xt1] = dist[xt] + 1;
	            }
	        }
	    }
	    return (dist[t] != -1);
	}

	inline int DFS(int xt, int minCap)
	{
	    if (minCap == 0) return 0;
	    if (xt == t) return minCap;
	    while (upTo[xt] < graf[xt].adj.size())
	    {
	        int currID = graf[xt].adj[upTo[xt]];
	        int xt1 = E[currID].v;
	        if (dist[xt1] != dist[xt] + 1)
	        {
	            upTo[xt]++;
	            continue;
	        }
	        int aug = DFS(xt1, min(minCap, E[currID].cap - E[currID].flow));
	        if (aug > 0)
	        {
	            E[currID].flow += aug;
	            if (currID&1) currID--; else currID++;
	            E[currID].flow -= aug;
	            return aug;
	        }
	        upTo[xt]++;
	    }
	    return 0;
	}
	inline int Dinic()
	{
	    int flow = 0;
	    while (true)
	    {
	        if (!BFS()) break;
	        for (int i=1;i<=v;i++) upTo[i] = 0;
	        while (true)
	        {
	            int currFlow = DFS(s, INF);
	            if (currFlow == 0) break;
	            flow += currFlow;
	        }
	    }
	    return flow;
	}
	inline void addEdge(int u, int v, int cap)
	{
		// cout << u << ' ' << v << ' ' << cap << endl;
	    Edge E1, E2;

	    E1.u = u, E1.v = v, E1.cap = cap, E1.flow = 0;
	    E2.u = v, E2.v = u, E2.cap = 0, E2.flow = 0;

	    graf[u].adj.push_back(idd++);
	    E.push_back(E1);
	    graf[v].adj.push_back(idd++);
	    E.push_back(E2);
	}
	#undef int
} F;

bool bad[100010];
vector <int> forb[100010];
void prop(int x) {
	bad[x] = true;
	for(auto i : forb[x]) {
		if(!bad[i]) {
			prop(i);
		}
	}
}

int main(int argc, char const *argv[])
{
	ios_base :: sync_with_stdio (false);
	cin.tie(0);

	int n, m;
	cin >> n >> m;
	for(int i = 1; i <= n; i++) {
		for(int j = 1; j <= n; j++) {
			if(i != j) {
				adj[i][j] = 1000000001;
			}
		}
		opt[i] = -inf;
	}
	for(int i = 1; i <= m; i++) {
		int u, v;
		cin >> u >> v;
		adj[u][v] = adj[v][u] = 1;
	}
	for(int k = 1; k <= n; k++) {
		for(int i = 1; i <= n; i++) {
			for(int j = 1; j <= n; j++) {
				adj[i][j] = min(adj[i][j], adj[i][k] + adj[k][j]);
			}
		}
	}

	int s, b, k;
	cin >> s >> b >> k;

	vector <pair <int, int>> v;

	for(int i = 1; i <= s; i++) {
		cin >> xp[i] >> a[i] >> f[i] >> p[i];
		v.emplace_back(a[i], i);
	}
	for(int i = 1; i <= b; i++) {
		cin >> xb[i] >> d[i] >> g[i];
		v.emplace_back(d[i], -i);
	}
	sort(v.begin(), v.end());
	for(auto i : v) {
		int id = abs(i.second);
		if(i.second > 0) {
			int x = xp[id];
			profit[id] = -inf;
			for(int j = 1; j <= n; j++) {
				if(adj[x][j] <= f[id]) {
					profit[id] = max(profit[id], opt[j] - p[id]);
				}
			}
		} else {
			int x = xb[id];
			opt[x] = max(opt[x], (long long) g[id]);
		}
	}
	for(int i = 1; i <= k; i++) {
		int u, v;
		cin >> u >> v;
		forb[v].push_back(u);
	}
	for(int i = 1; i <= s; i++) {
		if(!bad[i] && profit[i] < -max_profit) {
			prop(i);
		}
	}
	F.s = s + 1;
	F.t = s + 2;
	F.v = s + 2;
	for(int i = 1; i <= s; i++) {
		if(bad[i]) continue;
		for(auto j : forb[i]) {
			if(!bad[j]) {
				F.addEdge(j, i, inf);
			}
		}
	}
	long long sum = 0;
	for(int i = 1; i <= s; i++) {
		if(!bad[i]) {
			if(profit[i] > 0) {
				F.addEdge(F.s, i, profit[i]);
				sum += profit[i];
			} else {
				F.addEdge(i, F.t, -profit[i]);
			}
		}
	}
	cout << sum - F.Dinic() << endl;
	return 0;
}

#include<bits/stdc++.h>
#define fst first
#define snd second
#define fore(i,a,b)for(int i=a,ThxDem=b;i<ThxDem;++i)
#define pb push_back
#define ALL(s)s.begin(),s.end()
#define FIN ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define SZ(s)int(s.size())
using namespace std;
typedef long long ll;
typedef pair<ll,ll>ii;

ll d[110][110],INF=1e18;
ll v[100010];
vector<ii>base[110];
vector<ll>bst[110];

struct Dinic{
int nodes,src,dst;
vector<int>dist,q,work;
struct edge{int to,rev;ll f,cap;};
vector<vector<edge>>g;
Dinic(int x):nodes(x),g(x),dist(x),q(x),work(x){}
void add_edge(int s,int t,ll cap){
g[s].pb((edge){t,SZ(g[t]),0,cap});
g[t].pb((edge){s,SZ(g[s])-1,0,0});
}
bool dinic_bfs(){
fill(ALL(dist),-1);dist[src]=0;
int qt=0;q[qt++]=src;
for(int qh=0;qh<qt;qh++){
int u=q[qh];
fore(i,0,SZ(g[u])){
edge&e=g[u][i];int v=g[u][i].to;
if(dist[v]<0&&e.f<e.cap)dist[v]=dist[u]+1,q[qt++]=v;
}
}
return dist[dst]>=0;
}
ll dinic_dfs(int u,ll f){
if(u==dst)return f;
for(int&i=work[u];i<SZ(g[u]);i++){
edge&e=g[u][i];
if(e.cap<=e.f)continue;
int v=e.to;
if(dist[v]==dist[u]+1){
ll df=dinic_dfs(v,min(f,e.cap-e.f));
if(df>0){e.f+=df;g[v][e.rev].f-=df;return df;}
}
}
return 0;
}
ll max_flow(int _src,int _dst){
src=_src;dst=_dst;
ll result=0;
while(dinic_bfs()){
fill(ALL(work),0);
while(ll delta=dinic_dfs(src,INF))result+=delta;
}
return result;
}
};

int main(){FIN;
int n,m;cin>>n>>m;
fore(i,0,n)fore(j,0,n)d[i][j]=INF*(i!=j);
fore(i,0,m){
int x,y;cin>>x>>y;d[x-1][y-1]=d[y-1][x-1]=1;
}
fore(k,0,n)fore(i,0,n)fore(j,0,n){
if(d[i][k]!=INF&&d[k][j]!=INF)d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
}
ll ans=0,s,b,k;cin>>s>>b>>k;
fore(i,0,s)v[i]=-INF;
vector<pair<ii,ii>>a(s);
fore(i,0,s)cin>>a[i].fst.fst>>a[i].fst.snd>>a[i].snd.fst>>a[i].snd.snd,a[i].fst.fst--;
fore(i,0,b){
ll x,di,g;cin>>x>>di>>g;x--;base[x].pb({di,g});
}
fore(i,0,n){
sort(ALL(base[i]));bst[i].resize(SZ(base[i]));
fore(j,0,SZ(base[i])){
bst[i][j]=base[i][j].snd;
if(j)bst[i][j]=max(bst[i][j],bst[i][j-1]);
}
}
Dinic nt(s+2);
fore(i,0,SZ(a)){
fore(j,0,n){
int top=upper_bound(ALL(base[j]),(ii){a[i].fst.snd,INF})-base[j].begin()-1;
if(d[a[i].fst.fst][j]<=a[i].snd.fst&&top>=0){
v[i]=max(v[i],bst[j][top]-a[i].snd.snd);
}
}
if(v[i]<0)nt.add_edge(i+1,s+1,-v[i]);
else ans+=v[i],nt.add_edge(0,i+1,v[i]);
}
fore(i,0,k){
int x,y;cin>>x>>y;nt.add_edge(x,y,INF);
}
cout<<ans-nt.max_flow(0,s+1)<<"\n";
}

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

template<typename T> struct Dinic {
	static const int MAXN = 100005, MAXM = 1000005;
	struct Edge { int to, next; T cap; } edge[MAXM];
	int head[MAXN], tot;
	void clear() { memset(head, -1, sizeof(head)); tot = 0; }
	Dinic() { clear(); }
	void add(int u, int v, T c) {
		edge[tot] = (Edge) { v, head[u], c };
		head[u] = tot++;
		edge[tot] = (Edge) { u, head[v], (T)0 };
		head[v] = tot++;
	}
	int dis[MAXN], que[MAXN], id[MAXN];
	bool bfs(int s, int t) {
		memset(dis, -1, sizeof(dis));
		memcpy(id, head, sizeof(id));
		int he = 0, ta = 0;
		dis[que[ta++] = s] = 0;
		while (he < ta) {
			int u = que[he++];
			for (int i = head[u]; ~i; i = edge[i].next) {
				int v = edge[i].to;
				if (dis[v] < 0 && edge[i].cap) {
					dis[que[ta++] = v] = dis[u] + 1;
					if (v == t) return true;
				}
			}
		}
		return false;
	}
	T dfs(int u, int t, T f) {
		if (u == t) return f;
		T flow = 0;
		for (int &i = id[u]; ~i; i = edge[i].next) {
			int v = edge[i].to;
			if (dis[v] > dis[u] && edge[i].cap) {
				int d = dfs(v, t, min(f, edge[i].cap));
				if (!d) continue;
				edge[i].cap -= d, edge[i ^ 1].cap += d;
				flow += d, f -= d;
				if (f == 0) return flow;
			}
		}
		dis[u] = -1; return flow;
	}
	T dinic(int s, int t, T inf = 1E9) {
		T flow = 0;
		while (bfs(s, t))
			flow += dfs(s, t, inf);
		return flow;
	}
};
const ll INF = 1E15;
Dinic<ll> din;
const int MAXN = 100005;
int dis[105][105], xx[MAXN], aa[MAXN], ff[MAXN], pp[MAXN], qq[MAXN], vis[MAXN], n, m;
struct Node { int d, g; } sh[MAXN];
vector<Node> nd[105];
bool cmp(const Node &a, const Node &b) { return a.d < b.d; }
int main() {
	scanf("%d%d", &n, &m);
	memset(dis, 0x3f, sizeof(dis));
	for (int i = 1; i <= n; i++) dis[i][i] = 0;
	for (int i = 1; i <= m; i++) {
		int u, v; scanf("%d%d", &u, &v);
		dis[u][v] = dis[v][u] = 1;
	}
	for (int i = 1; i <= n; i++)
	for (int j = 1; j <= n; j++)
	for (int k = 1; k <= n; k++)
		dis[j][k] = min(dis[i][j] + dis[i][k], dis[j][k]);
	int S, B, K; scanf("%d%d%d", &S, &B, &K);
	for (int i = 1; i <= S; i++) {
		scanf("%d%d%d%d", xx + i, aa + i, ff + i, pp + i);
		sh[i] = (Node) { aa[i], i };
	}
	sort(sh + 1, sh + 1 + S, cmp);
	for (int i = 1; i <= B; i++) {
		int x, d, g; scanf("%d%d%d", &x, &d, &g);
		nd[x].push_back((Node) { d, g });
	}
	for (int i = 1; i <= n; i++) {
		sort(nd[i].begin(), nd[i].end(), cmp);
		int mx = 0;
		for (Node &d : nd[i]) {
			mx = max(mx, d.g);
			d.g = mx;
		}
	}
	fill(qq + 1, qq + 1 + S, -1E9-555);
	for (int i = 1; i <= n; i++) {
		int s = nd[i].size();
		for (int j = 1, k = 0; j <= S; j++) {
			for (; k < s && nd[i][k].d <= sh[j].d; ++k);
			if (k > 0 && dis[i][xx[sh[j].g]] <= ff[sh[j].g])
				qq[sh[j].g] = max(qq[sh[j].g], nd[i][k - 1].g);
		}
	}
	for (int i = 1; i <= S; i++) pp[i] = qq[i] - pp[i];
	for (int i = 1; i <= K; i++) {
		int u, v; scanf("%d%d", &u, &v);
		din.add(u, v, INF);
		vis[u] = vis[v] = 1;
	}
	ll ans = 0;
	int s = S + 1, t = s + 1;
	for (int i = 1; i <= S; i++) if (!vis[i] && pp[i] > 0) ans += pp[i];
	for (int i = 1; i <= S; i++) if (vis[i]) {
		if (pp[i] > 0) din.add(s, i, pp[i]), ans += pp[i];
		else din.add(i, t, -pp[i]);
	}
	printf("%lld\n", ans - din.dinic(s, t, INF));
	return 0;
}

#include <bits/stdc++.h>

using namespace std;

struct Dinic {
    //using F = int; const static F INF = 0x3f3f3f3f;
    using F = long long; const static F INF = 0x3f3f3f3f3f3f3f3f;
    struct Edge {
        int v, bro; F cap;
        Edge() {}
        Edge(int _v, int _bro, F _cap) : v(_v), bro(_bro), cap(_cap) {}
    };
    vector<Edge> e;
    vector<int> pos, cur;
    int n, s, t, m;
    Dinic(int _n, int _s, int _t) : n(_n), s(_s), t(_t), m(0) {
        pos.assign(n, -1);
        cur.resize(n);
        d.resize(n);
        e.reserve(4e5);
    }
    void add(int u, int v, F c=INF) {
        assert(u < n && v < n);
        e.emplace_back(v, pos[u], c); pos[u] = m++;
        e.emplace_back(u, pos[v], 0); pos[v] = m++;
    }
    vector<int> d;
    // build layer graph
    bool bfs() {
        fill(d.begin(), d.end(), -1);
        d[s] = 0;
        queue<int> q; q.push(s);
        while (!q.empty()) {
            int u = q.front(); q.pop();
            for (int i = cur[u] = pos[u]; i != -1; i = e[i].bro) {
                int v = e[i].v;
                if (d[v] == -1 && e[i].cap != 0) {
                    d[v] = d[u] + 1;
                    q.push(v);
                }
            }
        }
        return d[t] != -1;
    }
    // find blocking flow
    F dfs(int u, F lim) {
        if (u == t) return lim;
        F tot = 0;
        for (int& i = cur[u]; i != -1; i = e[i].bro) {
            int v = e[i].v;
            if (e[i].cap != 0 && d[v] == d[u] + 1) {
                F flow = dfs(v, min(e[i].cap, lim-tot));
                tot += flow;
                e[i].cap -= flow;
                e[i^1].cap += flow;
                if (tot == lim) return lim;
            }
        }
        return tot;
    }
    F flow() {
        F res = 0;
        while (bfs()) {
            res += dfs(s, INF);
        }
        return res;
    }
};

struct ProjectSelection {
    int n;
    int s,t;
    Dinic mc;
    using F = Dinic::F;
    F positive;

    ProjectSelection(int _n) : n(_n)
        , s(n)
        , t(n+1)
        , mc(n+2, s, t)
        , positive(0)
    {}

    void add_proj(int i, F profit) {
        if (profit >= 0) {
            mc.add(s, i, profit);
            positive += profit;
        } else {
            mc.add(i, t, -profit);
        }
    }

    // !!Caution: proj without dep-relation not included in flow
    // u,v: [0..n)
    void add_dep(int u, int v) {
        mc.add(u, v);
    }

    F profit() {
        return positive - mc.flow();
    }
};

template <typename T=int>
struct Compress {
    map<T, int> id;
    vector<T> num;

    inline int get_id(T x) {
        if (!id.count(x)) {
            id[x] = num.size();
            num.emplace_back(x);
        }
        return id[x];
    }
    inline int get_num(int i) {
        assert(0 <= i && i < num.size());
        return num[i];
    }
};

struct ProjectSelectionDumper {
    using F = Dinic::F;
    F sum;
    ProjectSelectionDumper(const vector<F>& profits, const vector<pair<int, int>>& deps) {
        vector<bool> trk(profits.size(), false);
        Compress<int> c;
        for (auto& p: deps) {
            c.get_id(p.first);
            c.get_id(p.second);
            trk[p.first] = true;
            trk[p.second] = true;
        }

        ProjectSelection ps(c.num.size());
        sum = 0;
        for (int i = 0; i < (int)profits.size(); i++) {
            if (trk[i]) {
                ps.add_proj(c.get_id(i), profits[i]);
            } else if (profits[i] > 0) {
                sum += profits[i];
            }
        }
        for (auto& p: deps) {
            int u = c.get_id(p.first);
            int v = c.get_id(p.second);
            ps.add_dep(u, v);
        }
        sum += ps.profit();
    }
};

using ll=long long;
const int INF = 0x3f3f3f3f;
const int N = 111;
int d[N][N];

void solve() {
    int n,m;
    cin >> n >> m;
    memset(d, INF, sizeof d);
    for (int _ = 0; _ < m; _++) {
        int x,y;
        cin >> x >> y;
        x--;y--;
        d[x][y] = d[y][x] = 1;
    }
    for (int i = 0; i < n; i++) {
        d[i][i] = 0;
    }
    for (int k = 0; k < n; k++) {
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                if (d[i][k] < INF && d[k][j] < INF) {// for negative
                    d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
                }
            }
        }
    }

    int s,b,k;
    cin >> s >> b >> k;
    vector<int> x(s), a(s), f(s);
    vector<ll> p(s);
    for (int i = 0; i < s; i++) {
        cin >> x[i] >> a[i] >> f[i] >> p[i];
        --x[i];
    }
    vector<map<int,int>> dg(n);
    for (int _ = 0; _ < b; _++) {
        int i,d,g;
        cin >> i >> d >> g;
        i--;
        dg[i][d] = max(dg[i][d], g);
    }
    for (int i = 0; i < n; i++) {
        int pre = 0;
        for (auto it = dg[i].begin(); it != dg[i].end(); it++) {
            it->second = pre = max(it->second, pre);
        }
    }

    for (int i = 0; i < s; i++) {
        int mx = -1;
        int u = x[i];
        for (int j = 0; j < n; j++) {
            if (!dg[j].empty() && f[i] >= d[u][j]) {
                auto it = dg[j].upper_bound(a[i]);
                if (it != dg[j].begin()) {
                    --it;
                    mx = max(mx, it->second);
                }
            }
        }
        if (mx < 0) p[i] = -(1ll<<62);
        else p[i] = mx - p[i];
    }

    vector<pair<int, int>> deps;
    for (int _ = 0; _ < k; _++) {
        int u,v;
        cin >> u >> v;
        u--;v--;
        deps.emplace_back(u, v);
    }

    ProjectSelectionDumper ps(p, deps);

    cout << ps.sum << "\n";
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    solve();
    cout << endl;
}

#include <bits/stdc++.h>
#define rep(i,n)for(int i=0;i<(n);i++)
#define MOD 1000000007
#define INF 0x3f3f3f3f
#define INFL 0x3f3f3f3f3f3f3f3f
using namespace std;
typedef long long ll;
#define int long long
typedef pair<int,int>P;

class Dinic {
private:
	struct Edge {
		ll to, cap, rev;
		Edge(ll t, ll c, ll r) :to(t), cap(c), rev(r) {}
	};
	ll V;
	std::vector<std::vector<Edge>> graph;
	std::vector<ll> level, iter;

public:
	Dinic(ll v) : V(v) {
		graph.resize(v);
		level.resize(v, -1);
		iter.resize(v, 0);
	}

	void add_edge(ll from, ll to, ll cap) {
		graph[from].emplace_back(to, cap, graph[to].size());
		graph[to].emplace_back(from, 0, graph[from].size() - 1);
	}

	void bfs(ll s) {
		std::fill(level.begin(), level.end(), -1);
		std::queue<ll> queue;
		level[s] = 0;
		queue.push(s);
		while (!queue.empty()) {
			ll v = queue.front(); queue.pop();
			for (ll i = 0; i < (ll)graph[v].size(); ++i) {
				Edge& e = graph[v][i];
				if (e.cap > 0 && level[e.to] < 0) {
					level[e.to] = level[v] + 1;
					queue.push(e.to);
				}
			}
		}
	}

	ll dfs(ll v, ll t, ll f) {
		if (v == t) return f;
		for (ll& i = iter[v]; i < (ll)graph[v].size(); ++i) {
			Edge& e = graph[v][i];
			if (e.cap > 0 && level[v] < level[e.to]) {
				ll d = dfs(e.to, t, std::min(f, e.cap));
				if (d > 0) {
					e.cap -= d;
					graph[e.to][e.rev].cap += d;
					return d;
				}
			}
		}
		return 0;
	}

	ll max_flow(ll s, ll t) {
		ll res = 0;
		while (true) {
			bfs(s);
			if (level[t] < 0) return res;
			std::fill(iter.begin(), iter.end(), 0);
			ll f;
			while ((f = dfs(s, t, LLONG_MAX)) > 0) {
				res += f;
			}
		}
	}
};

int dist[200][200];
int x[200000],a[200000],f[200000],p[200000];
int y[200000],d[200000],g[200000];
vector
v[200][200];
bool used[200000];
int s1[2000],s2[2000];

signed main(){
	int n,m;cin>>n>>m;
	memset(d,0x3f,sizeof(d));
	rep(i,n)dist[i][i]=0;
	rep(i,m){
		int a,b;scanf("%lld%lld",&a,&b);a--;b--;
		if(a==b)continue;
		dist[a][b]=dist[b][a]=1;
	}
	rep(k,n)rep(i,n)rep(j,n){
		dist[i][j]=min(dist[i][j],dist[i][k]+dist[k][j]);
	}
	int s,b,k;scanf("%lld%lld%lld",&s,&b,&k);
	rep(i,s){
		scanf("%lld%lld%lld%lld",&x[i],&a[i],&f[i],&p[i]);x[i]--;
	}
	rep(i,b){
		scanf("%lld%lld%lld",&y[i],&d[i],&g[i]);y[i]--;
	}
	rep(i,k){
		scanf("%lld%lld",&s1[i],&s2[i]);s1[i]--;s2[i]--;
		used[s1[i]]=used[s2[i]]=true;
	}
	rep(i,n){
		rep(j,b){
			if(dist[i][y[j]]!=INFL){
				v[i][dist[i][y[j]]].push_back(P(d[j],g[j]));
			}
		}
		rep(j,n){
			sort(v[i][j].begin(),v[i][j].end(),[](P a,P b){
				if(a.first==b.first)return a.second>b.second;
				return a.first<b.first;
			});
			vector
u;
			for(P p:v[i][j]){
				if(u.empty()||u.back().second<p.second)u.push_back(p);
			}
			v[i][j]=u;
		}
	}
	ll ans=0;
	vector<int>vs;
	rep(i,s){
		if(used[i])vs.push_back(i);
	}
	sort(vs.begin(),vs.end());
	vs.erase(unique(vs.begin(),vs.end()),vs.end());
	Dinic dinic(vs.size()+2);
	rep(i,s){
		int Max=-1;
		rep(j,min(n,f[i]+1)){
			int it=upper_bound(v[x[i]][j].begin(),v[x[i]][j].end(),P(a[i],INT_MAX))-v[x[i]][j].begin();
			if(it){
				it--;
				Max=max(Max,v[x[i]][j][it].second);
			}
		}
		if(!used[i]){
			if(Max-p[i]>0)ans+=Max-p[i];
		}
		else{
			int id=lower_bound(vs.begin(),vs.end(),i)-vs.begin();
			if(Max==-1){
				dinic.add_edge(vs.size(),id,0);
				dinic.add_edge(id,vs.size()+1,LLONG_MAX/100000);
			}
			else if(Max-p[i]>0){
				ans+=Max-p[i];
				dinic.add_edge(vs.size(),id,Max-p[i]);
				dinic.add_edge(id,vs.size()+1,0);
			}
			else{
				dinic.add_edge(vs.size(),id,0);
				dinic.add_edge(id,vs.size()+1,p[i]-Max);
			}
		}
	}
	rep(i,k){
		int S1=lower_bound(vs.begin(),vs.end(),s1[i])-vs.begin();
		int S2=lower_bound(vs.begin(),vs.end(),s2[i])-vs.begin();
		if(S1==S2)continue;
		dinic.add_edge(S1,S2,LLONG_MAX/100000);
	}
	cout<<ans-dinic.max_flow(vs.size(),vs.size()+1)<<endl;
}

#include <algorithm>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>
#define debug(...) //fprintf(stderr, __VA_ARGS__)
using namespace std;
inline char nc()
{
    return getchar();
	static char buf[100000], *l = buf, *r = buf;
	return l==r&&(r=(l=buf)+fread(buf,1,100000,stdin),l==r)?EOF:*l++;
}
template<class T> void read(T &x)
{
	x = 0; int f = 1, ch = nc();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=nc();}
	while(ch>='0'&&ch<='9'){x=x*10-'0'+ch;ch=nc();}
	x *= f;
}
typedef long long ll;
const int inf = 1e9 + 1;
const int maxn = 100 + 5;
const int maxs = 1e5 + 5;
const int maxb = 1e5 + 5;
int n, m;
int s, b, k;
int st, ed;
int val[maxn];
int dis[maxn][maxn];
int head[maxs];
vector<int> adj[maxn];
struct data
{
    int a, b, c, d, id;
    inline bool operator < (const data &other) const
    {
        return b < other.b;
    }
} A[maxs], B[maxb];
struct edge
{
    int to, nex;
    ll cap, flow;
    edge(int to=0,int nex=0,ll cap=0,ll flow=0):to(to),nex(nex),cap(cap),flow(flow){}
};
vector<edge> G;
inline void adde(int u, int v)
{
    adj[u].push_back(v);
    adj[v].push_back(u);
}
inline void addedge(int u, int v, ll c)
{
    G.push_back(edge(v, head[u], c, 0)), head[u] = G.size() - 1;
    G.push_back(edge(u, head[v], 0, 0)), head[v] = G.size() - 1;
}
namespace dinic
{
    int dis[maxs], cur[maxs];
    bool BFS()
    {
        static int q[maxs];
        int hd = 0, tl = 0;
        memset(dis, -1, sizeof(dis));
        dis[st] = 0;
        q[tl++] = st;
        while(hd < tl)
        {
            int u = q[hd++];
            for(int i = head[u]; ~i; i = G[i].nex)
            {
                int v = G[i].to;
                if(dis[v] == -1 && G[i].cap != G[i].flow)
                {
                    dis[v] = dis[u] + 1;
                    q[tl++] = v;
                }
            }
        }
        return dis[ed] != -1;
    }
    ll DFS(int u, ll flow)
    {
        if(u == ed || flow == 0) return flow;
        ll rec = flow;
        for(int &i = cur[u]; ~i; i = G[i].nex)
        {
            int v = G[i].to;
            if(dis[v] == dis[u] + 1)
            {
                ll d = DFS(v, min(flow, G[i].cap - G[i].flow));
                G[i].flow += d;
                G[i ^ 1].flow -= d;
                flow -= d;
                if(flow == 0) break;
            }
        }
        return rec - flow;
    }
    ll maxflow()
    {
        ll flow = 0;
        while(BFS())
        {
            memcpy(cur, head, sizeof(head));
            flow += DFS(st, 1e18);
        }
        return flow;
    }
}
int adde(int x)
{
    int mx = -1;
    for(int i = 1; i <= n; ++i) if(dis[ A[x].a ][i] <= A[x].c)
    {
        mx = max(mx, val[i]);
    }
    if(mx == -1)
    {
        addedge(A[x].id, ed, 1e18);
        return 0;
    }
    mx -= A[x].d;
    if(mx < 0)
    {
        addedge(A[x].id, ed, -mx);
        return 0;
    }
    addedge(st, A[x].id, mx);
    return mx;
}
void BFS(int st)
{
    static int q[maxn];
    int hd = 0, tl = 0;
    for(int i = 1; i <= n; ++i) dis[st][i] = inf;
    dis[st][st] = 0;
    q[tl++] = st;
    while(hd < tl)
    {
        int u = q[hd++];
        for(unsigned int i = 0; i < adj[u].size(); ++i)
        {
            int v = adj[u][i];
            if(dis[st][v] == inf)
            {
                dis[st][v] = dis[st][u] + 1;
                q[tl++] = v;
            }
        }
    }
}
void init()
{
    for(int i = 1; i <= n; ++i) BFS(i);
}
ll solve()
{
    init();
    sort(A + 1, A + s + 1);
    sort(B + 1, B + b + 1);
    ll an = 0;
    int i = 1, j = 1;
    st = 0, ed = s + 1;
    memset(val, -1, sizeof(val));
    while(i <= s && j <= b)
    {
        if(B[j].b <= A[i].b)
        {
            val[ B[j].a ] = max(val[ B[j].a ], B[j].c);
            ++j;
        }
        else
        {
            an += adde(i++);
        }
    }
    while(i <= s) an += adde(i++);
    return an - dinic :: maxflow();
}
int main()
{
    read(n), read(m);
    for(int i = 1; i <= m; ++i)
    {
        int u, v; read(u), read(v);
        adde(u, v);
    }
    read(s), read(b), read(k);
    for(int i = 1; i <= s; ++i)
    {
        read(A[i].a), read(A[i].b), read(A[i].c), read(A[i].d);
        A[i].id = i;
    }
    for(int i = 1; i <= b; ++i)
    {
        read(B[i].a), read(B[i].b), read(B[i].c);
    }
    memset(head, -1, sizeof(head));
    for(int i = 1; i <= k; ++i)
    {
        int s1, s2; read(s1), read(s2);
        addedge(s1, s2, 1e18);
    }
    printf("%I64d\n", solve());
    return 0;
}

//Author: Heltion
//Date: 07-31-2019
#include<bits/stdc++.h>
using namespace std;
using LL = long long;
template<typename T>void no(T s){cout << s; exit(0);}
void no(){cout << "NO"; exit(0);}
constexpr LL maxm = 120;
constexpr LL maxn = 120000;
LL d[maxm][maxm];
LL sx[maxn], a[maxn], f[maxn], p[maxn], bx[maxn], dd[maxn], g[maxn];
struct FlowEdge {
    int v, u;
    long long cap, flow = 0;
    FlowEdge(int v, int u, long long cap) : v(v), u(u), cap(cap) {}
};

struct Dinic {
    const long long flow_inf = 1e18;
    vector<FlowEdge> edges;
    vector<vector<int>> adj;
    int n, m = 0;
    int s, t;
    vector<int> level, ptr;
    queue<int> q;

    Dinic(int n, int s, int t) : n(n), s(s), t(t) {
        adj.resize(n);
        level.resize(n);
        ptr.resize(n);
    }

    void add_edge(int v, int u, long long cap) {
        edges.emplace_back(v, u, cap);
        edges.emplace_back(u, v, 0);
        adj[v].push_back(m);
        adj[u].push_back(m + 1);
        m += 2;
    }

    bool bfs() {
        while (!q.empty()) {
            int v = q.front();
            q.pop();
            for (int id : adj[v]) {
                if (edges[id].cap - edges[id].flow < 1)
                    continue;
                if (level[edges[id].u] != -1)
                    continue;
                level[edges[id].u] = level[v] + 1;
                q.push(edges[id].u);
            }
        }
        return level[t] != -1;
    }

    long long dfs(int v, long long pushed) {
        if (pushed == 0)
            return 0;
        if (v == t)
            return pushed;
        for (int& cid = ptr[v]; cid < (int)adj[v].size(); cid++) {
            int id = adj[v][cid];
            int u = edges[id].u;
            if (level[v] + 1 != level[u] || edges[id].cap - edges[id].flow < 1)
                continue;
            long long tr = dfs(u, min(pushed, edges[id].cap - edges[id].flow));
            if (tr == 0)
                continue;
            edges[id].flow += tr;
            edges[id ^ 1].flow -= tr;
            return tr;
        }
        return 0;
    }

    long long flow() {
        long long f = 0;
        while (true) {
            fill(level.begin(), level.end(), -1);
            level[s] = 0;
            q.push(s);
            if (!bfs())
                break;
            fill(ptr.begin(), ptr.end(), 0);
            while (long long pushed = dfs(s, flow_inf)) {
                f += pushed;
            }
        }
        return f;
    }
};
vector<pair<LL, LL>> v[maxn];
int main(){
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	cout.tie(nullptr);
	cout << fixed << setprecision(20);
	LL n, m;
	cin >> n >> m;
	for(LL i = 1; i <= n; i += 1)
		for(LL j = 1; j <= n; j += 1) if(i != j) d[i][j] = 1e10;
	for(LL i = 1; i <= m; i += 1){
		LL u, v;
		cin >> u >> v;
		if(u != v) d[u][v] = d[v][u] = 1;
	}
	for(LL k = 1; k <= n; k += 1)
		for(LL i = 1; i <= n; i += 1)
			for(LL j = 1; j <= n; j += 1)
				d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
	LL s, b, k;
	cin >> s >> b >> k;
	LL ans = 0;
	for(LL i = 1; i <= s; i += 1)
		cin >> sx[i] >> a[i] >> f[i] >> p[i];
	for(LL i = 1; i <= b; i += 1)
		cin >> bx[i] >> dd[i] >> g[i];

	Dinic dinic(s + 2, 0, s + 1);
	for(LL i = 1; i <= k; i += 1){
		int u, v;
		cin >> u >> v;
		dinic.add_edge(u, v, 1e17);
	}
	for(LL j = 1; j <= b; j += 1)
		v[bx[j]].push_back(make_pair(dd[j], g[j]));
	for(LL j = 1; j <= n; j += 1){
		sort(v[j].begin(), v[j].end());
		for(LL i = 1; i < (LL)v[j].size(); i += 1)
			v[j][i].second = max(v[j][i].second, v[j][i - 1].second);
	}
	for(LL i = 1; i <= s; i += 1){
		LL x = -1e15;
		for(LL j = 1; j <= n; j += 1)
			if(d[sx[i]][j] <= f[i] and v[j].size()) {
				auto p = upper_bound(v[j].begin(), v[j].end(), make_pair(a[i], (LL)1e17));
				if(p == v[j].begin()) continue;
				p --;
				x = max(x, p->second);
			}
		LL y = x - p[i];
		if(y > 0){
			ans += y;
			dinic.add_edge(0, i, y);
		}
		else dinic.add_edge(i, s + 1, -y);
	}
	cout << ans - dinic.flow();
	return 0;
}

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int mod=1e9+7;
const int maxm=100+10;
const int maxn=3e5+10;
const int N=1e5+10;
const int inf=0x3f3f3f3f;
const ll inf1=0x3f3f3f3f3f3f3f3f;
namespace io {
    const int SIZE = (1 << 21) + 1;
    char ibuf[SIZE], *iS, *iT, obuf[SIZE], *oS = obuf, *oT = oS + SIZE - 1, c, qu[55]; int f, qr;
    // getchar
    #define gc() (iS == iT ? (iT = (iS = ibuf) + fread (ibuf, 1, SIZE, stdin), (iS == iT ? EOF : *iS ++)) : *iS ++)
    // print the remaining part
    inline void flush () {
        fwrite (obuf, 1, oS - obuf, stdout);
        oS = obuf;
    }
    // putchar
    inline void putc (char x) {
        *oS ++ = x;
        if (oS == oT) flush ();
    }
    template<typename A>
    inline bool read (A &x) {
        for (f = 1, c = gc(); c < '0' || c > '9'; c = gc()) if (c == '-') f = -1;else if(c==EOF)return 0;
        for (x = 0; c <= '9' && c >= '0'; c = gc()) x = x * 10 + (c & 15); x *= f;
        return 1;
    }
    inline bool read (char &x) {
        while((x=gc())==' '||x=='\n' || x=='\r');
        return x!=EOF;
    }
    inline bool read(char *x){
        while((*x=gc())=='\n' || *x==' '||*x=='\r');
        if(*x==EOF)return 0;
        while(!(*x=='\n'||*x==' '||*x=='\r'||*x==EOF))*(++x)=gc();
        *x=0;
        return 1;
    }
    template<typename A,typename ...B>
    inline bool read(A &x,B &...y){
        return read(x)&&read(y...);
    }
    template<typename A>
    inline bool write (A x) {
        if (!x) putc ('0'); if (x < 0) putc ('-'), x = -x;
        while (x) qu[++ qr] = x % 10 + '0',  x /= 10;
        while (qr) putc (qu[qr --]);
        return 0;
    }
    inline bool write (char x) {
        putc(x);
        return 0;
    }
    inline bool write(const char *x){
        while(*x){putc(*x);++x;}
        return 0;
    }
    inline bool write(char *x){
        while(*x){putc(*x);++x;}
        return 0;
    }
    template<typename A,typename ...B>
    inline bool write(A x,B ...y){
        return write(x)||write(y...);
    }
    //no need to call flush at the end manually!
    struct Flusher_ {~Flusher_(){flush();}}io_flusher_;
}
using io :: read;
using io :: putc;
using io :: write;
int dis[maxm][maxm];
map<int,int> mp;
struct base{
	int def,gold,mmax;
	friend bool operator<(base a,base b)
	{
		return a.def<b.def;
	}
};
struct ship{
	int x,att,fuel,pri;
}a[N];
vector<base> v[maxm];
ll val[N];
int s,t;
int now[N],dep[N],head[N];
struct edge{
	int v;
	ll w;
	int nxt;
}e[maxn];
int ecnt;
void addedge(int u,int v,ll w)
{
	e[ecnt]={v,w,head[u]};
	head[u]=ecnt++;
	e[ecnt]={u,0,head[v]};
	head[v]=ecnt++;
}
int bfs()//重新建图，按层次建图
{
    queue<int> q;
    while(!q.empty())
        q.pop();
    for(int i=s;i<=t;i++)
    {
    	dep[i]=-1;
    	now[i]=-1; //now[i]表示i的当前弧
    }
    dep[s] = 0; //dep为层次
    q.push(s);
    now[s]=head[s];
    while(!q.empty()){
        int u = q.front();
        q.pop();
        for(int i=head[u]; i!=-1; i=e[i].nxt){
        	int v=e[i].v;
            if(e[i].w > 0 && dep[v] == -1){//如果可以到达且还没有访问，可以到达的条件是剩余容量大于0，没有访问的条件是当前层数还未知
                dep[v] = dep[u] + 1;
                now[v]=head[v];
                q.push(v);
            }
        }
    }
    return dep[t] != -1;
}
ll dfs(int u, ll mi)//查找路径上的最小流量
{
    if(mi==0||u == t)
        return mi;
    ll tmp,sum=0;
    for(int i=now[u]; i!=-1&&mi; i=e[i].nxt){
    	now[u]=i; //当前弧优化
    	int v=e[i].v;
        if(e[i].w > 0 && dep[v] == dep[u] + 1){
			tmp = dfs(v, min(mi, e[i].w));
            e[i].w -= tmp;
            e[i^1].w += tmp;
            sum+=tmp; //一次增广跑多条路，sum为流量总和
            mi-=tmp; //用掉了tmp
            if(!mi) break;
        }
    }
    return sum;
}
ll dinic()
{
    ll ans = 0;
    while(bfs()){
        ans+=dfs(s,inf1);
    }
    return ans;
}
int main()
{
	memset(head,-1,sizeof(head));
	memset(dis,0x3f,sizeof(dis));
	int n,m;
	read(n,m);
	for(int i=1;i<=n;i++) dis[i][i]=0;
	for(int i=1;i<=m;i++)
	{
		int u,v;
		read(u,v);
		dis[u][v]=dis[v][u]=1;
	}
	for(int k=1;k<=n;k++)
		for(int i=1;i<=n;i++)
			for(int j=1;j<=n;j++)
				dis[i][j]=min(dis[i][k]+dis[k][j],dis[i][j]);
	int snum,bnum,k;
	read(snum,bnum,k);
	//assert(bnum<=n);
	for(int i=1;i<=snum;i++)
	{
		int x,att,fu,pri;
		read(x,att,fu,pri);
		a[i]={x,att,fu,pri};
	}
	for(int i=1;i<=bnum;i++)
	{
		int x,def,gol;
		read(x,def,gol);
		//assert((!mp[x])||mp[x]==def);
		//b[x]={def,gol};
		//mp[x]=def;
		v[x].push_back({def,gol,gol});
	}
	for(int i=1;i<=n;i++)
	{
		sort(v[i].begin(),v[i].end());
		for(int j=1;j<v[i].size();j++) v[i][j].mmax=max(v[i][j].gold,v[i][j-1].mmax);
	}
	for(int i=1;i<=snum;i++) val[i]=-inf1;
	for(int i=1;i<=snum;i++)
	{
		for(int j=1;j<=n;j++)
		{
			if(a[i].fuel>=dis[a[i].x][j])
			{
				//val[i]=max(val[i],b[j].gold-a[i].pri);
				//int pos=v[a[i].x].lower_bound({a[i].att,inf,0})-v[a[i].x].begin();
				int l=0,r=v[j].size()-1,pos=-1;
				while(l<=r)
				{
					int mid=l+r>>1;
					if(v[j][mid].def<=a[i].att)
					{
						l=mid+1,pos=mid;
					}
					else r=mid-1;
				}
				if(pos<0) continue;
				val[i]=max(val[i],0ll+v[j][pos].mmax-a[i].pri);
			}
		}
	}
	s=0,t=snum+1;
	for(int i=1;i<=k;i++)
	{
		int u,v;
		read(u,v);
		addedge(u,v,inf1);
	}
	ll tot=0;
	for(int i=1;i<=snum;i++)
	{
		//printf("val[%d]=%d\n",i,val[i]);
		//if(val[i]<=-inf) continue;
		if(val[i]>=0)
		{
			tot+=val[i];
			addedge(s,i,val[i]);
		}
		if(val[i]<0) addedge(i,t,-val[i]);
	}
	tot-=dinic();
	printf("%lld\n",tot);
	return 0;
}

#include <bits/stdc++.h>
#define long long long

using namespace std;

struct Edge {
    int from, to, index;
    long cap, flow;
    Edge(int from, int to, long cap, long flow, int index) :
    from(from), to(to), index(index), cap(cap), flow(flow) {}
};

struct Dinic {
    int N;
    vector<vector<Edge> > G;
    vector<Edge *> dad;
    vector<int> Q;

    Dinic(int N) : N(N), G(N), dad(N), Q(N) {}

    void AddEdge(int from, int to, long cap) {
        G[from].push_back(Edge(from, to, cap, 0, G[to].size()));
        if (from == to) G[from].back().index++;
        G[to].push_back(Edge(to, from, 0, 0, G[from].size() - 1));
    }

    long BlockingFlow(int s, int t) {
        fill(dad.begin(), dad.end(), nullptr);
        dad[s] = &G[0][0] - 1;

        int head = 0, tail = 0;
        Q[tail++] = s;
        while (head < tail) {
            int x = Q[head++];
            for (int i = 0; i < G[x].size(); i++) {
                Edge &e = G[x][i];
                if (!dad[e.to] && e.cap - e.flow > 0) {
                    dad[e.to] = &G[x][i];
                    Q[tail++] = e.to;
                }
            }
        }
        if (!dad[t]) return 0;

        long totflow = 0;
        for (int i = 0; i < G[t].size(); i++) {
            Edge *start = &G[G[t][i].to][G[t][i].index];
            long amt = 1e18;
            for (Edge *e = start; amt && e != dad[s]; e = dad[e->from]) {
                if (!e) { amt = 0; break; }
                amt = min(amt, e->cap - e->flow);
            }
            if (amt == 0) continue;
            for (Edge *e = start; amt && e != dad[s]; e = dad[e->from]) {
                e->flow += amt;
                G[e->to][e->index].flow -= amt;
            }
            totflow += amt;
        }
        return totflow;
    }

    long GetMaxFlow(int s, int t) {
        long totflow = 0;
        while (long flow = BlockingFlow(s, t))
            totflow += flow;
        return totflow;
    }
};

int n, m, k, s, b;
int d[100][100];
int sa[100000];
long sp[100000], sbest[100000];
vector<int> rs[100];
map<int, long> gold[100];

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);

    cin >> n >> m;
    for (int i = 0; i < n; ++i) for (int j = 0; j < n; ++j) d[i][j] = -1;
    for (int i = 0; i < n; ++i) d[i][i] = 0;
    for (int i = 0; i < m; ++i) {
        int u, v; cin >> u >> v; u--; v--;
        if (d[u][v] == -1) d[u][v] = d[v][u] = 1;
    }
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < n; ++j) for (int k = 0; k < n; ++k) {
            if (d[j][i] == -1 || d[i][k] == -1) continue;
            d[j][k] = min(d[j][k] == -1 ? (int)1e9 : d[j][k], d[j][i] + d[i][k]);
        }
    }

    cin >> s >> b >> k;

    for (int i = 0; i < s; ++i) {
        int sx, sf;
        cin >> sx >> sa[i] >> sf >> sp[i]; sx--;
        sbest[i] = -1e18;
        for (int j = 0; j < n; ++j) {
            if (d[sx][j] != -1 && sf >= d[sx][j])
                rs[j].push_back(i);
        }
    }

    for (int i = 0; i < b; ++i) {
        int bx, bd, bg; cin >> bx >> bd >> bg; bx--;
        gold[bx][bd] = max(gold[bx][bd], (long)bg);
    }

    for (int i = 0; i < n; ++i) {
        vector<pair<int, long>> v;
        for (auto it : gold[i])
            v.push_back({it.first, max(v.empty() ? 0 : v.back().second, it.second)});
        sort(rs[i].begin(), rs[i].end(), [](int a, int b) {
            return sa[a] < sa[b];
        });

        int j = 0;
        for (int k = 0; k < v.size(); ++k) {
            while (j < rs[i].size() && sa[rs[i][j]] < v[k].first) j++;
            while (j < rs[i].size() && (k == v.size()-1 ||
                sa[rs[i][j]] < v[k+1].first)) {
                sbest[rs[i][j]] = max(sbest[rs[i][j]], v[k].second - sp[rs[i][j]]);
                j++;
            }
        }
    }

    long res = 0;
    for (int i = 0; i < s; ++i) if (sbest[i] >= 0) res += sbest[i];

    Dinic dinic(s+2);
    for (int i = 0; i < s; ++i) {
        if (sbest[i] >= 0) dinic.AddEdge(0, i+2, sbest[i]);
        else dinic.AddEdge(i+2, 1, -sbest[i]);
    }
    for (int i = 0; i < k; ++i) {
        int u, v; cin >> u >> v; u--; v--;
        dinic.AddEdge(u+2, v+2, 1e18);
    }
    res -= dinic.GetMaxFlow(0, 1);

    cout << res << "\n";
}

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef ll F;
const int N    = 1e2 + 10;
const int maxs = 1e5 + 10;
const int maxn = 2e3 + 10;
const int maxm = 6e3 + 10;
const ll INF  = 1e14+10;
const F  INF_CAP = INF;
/*
31962378494827
20000000000000
*/

struct spaceship{
    int x,a,f,p;
}sp[maxs];
struct base {
    int d,g;
    bool operator < (const base& b)const {
        return d < b.d;
    }
};

ll best_goal[maxs];

vector<base> ba[N];
vector<int>  pre[N];
vector<int>  g[maxs];
bool used[maxs];
int w[N][N],id[maxs];

struct Dinic{
    int n,m,s,t,pos;
    int d[maxn],head[maxn],que[maxn],ptr[maxn];
    int to[maxm],nxt[maxm];
    F  cap[maxm];
    void init() {
        memset(head,-1,sizeof head);
    }
    void addedge(int a,int b,F c) {
//        printf("%d %d %lld\n",a,b,c);
//        printf("%d\n",m);
        cap[m] = c;to[m] = b;nxt[m] = head[a];head[a] = m++;
        cap[m] = 0;to[m] = a;nxt[m] = head[b];head[b] = m++;
    }
    bool bfs() {
        pos = 0;
        memset(d,-1,sizeof d);
        que[pos++] = s;
        d[s] = 0;
        for(int i = 0;i < pos;i++) {
            int x = que[i];
            for(int u = head[x];~u;u = nxt[u]) {
                if(d[to[u]] == -1&&cap[u]) {
                    d[to[u]] = d[x] + 1;
                    que[pos++] = to[u];
                    if(d[t] != -1) return true;
                }
            }
        }
        return d[t] != -1;
    }
    F dfs(int o,F mi) {
        if(o == t||mi == 0) return mi;
        F res = 0;
        for(int &x = ptr[o];~x;x = nxt[x]) if(d[to[x]] == d[o] + 1&&cap[x]){
            F tmp = dfs(to[x],min(mi,cap[x]));
            cap[x] -= tmp;
            cap[x^1] += tmp;
            if(tmp > 0) return tmp;
        }
        return res;
    }
    F maxflow(int s,int t) {
        this->s = s;this->t = t;
        F res = 0;
        while(bfs()) {
            memcpy(ptr,head,sizeof head);
            res += dfs(s,INF_CAP);
        }
        return res;
    }
}D;

int main() {
    D.init();
    int n,m,s,b,k;
    scanf("%d%d",&n,&m);
    for(int i = 1;i <= n;i++) fill(w[i] + 1,w[i] + 1 + n,n),w[i][i] = 0;
    for(int i = 0;i < m;i++) {
        int a,b;
        scanf("%d%d",&a,&b);
        w[b][a] = w[a][b] = min(w[a][b],1);
    }
    for(int d = 1;d <= n;d++) {
        for(int i = 1;i <= n;i++) {
            for(int j = 1;j <= n;j++) {
                w[i][j] = min(w[i][j],w[i][d] + w[d][j]);
            }
        }
    }
    scanf("%d%d%d",&s,&b,&k);
    for(int i = 1;i <= s;i++) {
        scanf("%d%d%d%d",&sp[i].x,&sp[i].a,&sp[i].f,&sp[i].p);
    }
    for(int i = 0;i < b;i++) {
        int x,d,g;
        scanf("%d%d%d",&x,&d,&g);
        ba[x].push_back(base{d,g});
    }
    for(int i = 1;i <= n;i++) if(ba[i].size()){
        int sz = (int)ba[i].size();
        sort(ba[i].begin(),ba[i].end());
        pre[i].resize(sz);
        pre[i][0] = ba[i][0].g;
        for(int j = 1;j < sz;j++) pre[i][j] = max(pre[i][j-1],ba[i][j].g);
    }
    for(int i = 1;i <= s;i++) {
        best_goal[i] = -INF_CAP;
        int x = sp[i].x;
        for(int j = 1;j <= n;j++) {
            if(w[x][j] <= sp[i].f) {
                int pos = upper_bound(ba[j].begin(),ba[j].end(),base{sp[i].a,0}) - ba[j].begin();
                --pos;
                if(pos >= 0) {
                    best_goal[i] = max(best_goal[i],(ll)pre[j][pos] - sp[i].p);
                }
            }
        }
    }
    for(int i = 0;i < k;i++) {
        int a,b;
        scanf("%d%d",&a,&b);
        g[a].push_back(b);
        used[a] = used[b] = 1;
    }
    ll ans = 0;
    int cnt = 0;
    for(int i = 1;i <= s;i++) {
        if(!used[i]) {
            if(best_goal[i] > 0) ans += best_goal[i];
        }
        else {
            id[i] = ++cnt;
        }
    }

    int st = 0,ed = cnt + 1;
    cnt = 0;
    for(int i = 1;i <= s;i++) {
        if(used[i]) {
            if(best_goal[i] >= 0) ans += best_goal[i],D.addedge(st,id[i],best_goal[i]);
            else D.addedge(id[i],ed,-best_goal[i]);
            for(auto& u:g[i]) D.addedge(id[i],id[u],INF_CAP);
        }
    }
    // printf("%lld\n",ans);
    ans -= D.maxflow(st,ed);
    printf("%lld\n",ans);
    return 0;
}

//new.cpp
/*
Author : Hocky Yudhiono
Min 07 Jul 2019 08:05:40  WIB
Current Local Time : 20:05:40

getchar_unlocked > getchar > cin without sync > scanf > cin with sync
bool operator<(const MyStruct& rhs) const

On how to print Long Double to 5 decimal places :
printf("%.5Lf",ans);

On how to get random numbers :
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count()); //For int
mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count()); //For LL
cout << rng() << endl;
shuffle(isi.begin(),isi.end(),rng);

__gcd(a,b)
__builtin_ffs(a) first on bit
__builtin_clz(a) count leading zero
__builtin_ctz(a) count trailing zero
__builtin_popcount(a) numbers of on bits

*/

//#include <unordered_map>
//#include <unordered_set>

//#include <random>
//#include <chrono>

//#include <ext/pb_ds/assoc_container.hpp>
//#include <ext/pb_ds/tree_policy.hpp>

#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cassert>
#include <cstring>
#include <iomanip>
#include <cstdio>
#include <limits>
#include <string>
#include <vector>
#include <cmath>
#include <deque>
#include <queue>
#include <stack>
#include <map>
#include <set>

//using namespace __gnu_pbds;
using namespace std;

#pragma comment(linker, "/stack:200000000")
#pragma GCC optimize("Ofast")
#pragma GCC optimize(3)
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#pragma GCC target("sse3","sse2","sse")
#pragma GCC target("avx","sse4","sse4.1","sse4.2","ssse3")
#pragma GCC target("f16c")
#pragma GCC optimize("inline","fast-math","unroll-loops","no-stack-protector")
// #pragma GCC diagnostic error "-fwhole-program"
// #pragma GCC diagnostic error "-fcse-skip-blocks"
// #pragma GCC diagnostic error "-funsafe-loop-optimizations"
// #pragma GCC diagnostic error "-std=c++14"
// #pragma GCC target ("string"...)
#pragma GCC push_options
#pragma GCC pop_options
#pragma GCC reset_options
#pragma GCC optimize ("O3")

typedef long long LL;
typedef long double LD;
typedef unsigned long long ULL;
typedef pair<int,int> PII;
typedef pair<long long,long long> PLL;
// typedef tree<long long, null_type, less<long long>, rb_tree_tag, tree_order_statistics_node_update> pbds;
//If the time limit is strict, try not to use long double

#define fbo find_by_order
#define ook order_of_key
#define popf pop_front
#define pf push_front
#define popb pop_back
#define mp make_pair
#define pb push_back
#define remove erase
#define fi first
#define se second

//Remember to undefine if the problem is interactive
#define endl '\n'
#define DEBUG(X) cout << ">>> DEBUG(" << __LINE__ << ") " << #X << " = " << (X) << endl

const double eps = 1e-9;
const int INFMEM = 63;
const int INF = 1061109567;
const LL LINF = 100000000000000LL;
const double DINF = numeric_limits<double>::infinity();
const LL MOD = 1000000007;
const int dx[8] = {1,0,-1,0,1,1,-1,-1};
const int dy[8] = {0,1,0,-1,1,-1,1,-1};
const double PI = 3.141592653589793;

#ifdef _WIN32
#define getchar_unlocked getchar
#endif
#define GETCHAR getchar_unlocked
inline void fastll(LL &input_number)
{
    input_number = 0;
    int ch = GETCHAR();
    int sign = 1;
    while(ch < '0' || ch > '9'){
        if(ch == '-') sign=-1;
        ch = GETCHAR();
    }
    while(ch >= '0' && ch <= '9'){
        input_number = (input_number << 3)+(input_number << 1) + ch-'0';
        ch = GETCHAR();
    }
    input_number *= sign;
}

inline void open(string a){
    freopen((a+".in").c_str(),"r",stdin);
    freopen((a+".out").c_str(),"w",stdout);
}

inline void fasterios(){
    //Do not use if interactive
    ios_base::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);
}

struct ShipDT{
	LL pos,att,fuel,price,profit;
};
struct BaseDT{
	LL pos,def,price;
};
struct dtE{
    LL power_,idx;
    bool type;
    //0 = ship
    //1 = base
    bool operator<(const dtE &other)const{
        if(power_ != other.power_) return power_ < other.power_;
        return type > other.type;
    }
};
LL n,m;
LL dist[105][105];
LL CurMaxgold[105];
vector <dtE> events;
LL ShipN,BaseN,DepM;
ShipDT ship[100005];
BaseDT base[100005];

struct dt{
    LL to,cap,backidx;
};
struct dta{
    LL pos, step;
};
LL ans;
LL s,e;

LL st[200005];
LL level[200005];

queue <dta> antri;
vector <dt> edge[200005];

void make_edge(LL u, LL v, LL capto, LL backcap){
    // cout << u << " " << v << " " << capto << " " << backcap << endl;
    LL szu = edge[u].size();
    LL szv = edge[v].size();
    edge[u].pb({v,capto,szv});
    edge[v].pb({u,backcap,szu});
    return;
}

void bfs(dta now){
    for(int i = 0;i < edge[now.pos].size();i++){
        LL nx = edge[now.pos][i].to;
        if(level[nx]) continue;
        if(edge[now.pos][i].cap == 0) continue;
        level[nx] = now.step+1;
        antri.push({nx,now.step+1});
    }
    return;
}

LL maxflow(LL pos,LL bcap){
    // cout << pos << " " << bcap << endl;
    if(pos == e) return bcap;
    for(;st[pos] < edge[pos].size();st[pos]++){
        LL i = st[pos];
        LL nx = edge[pos][i].to;
        if(level[nx] != level[pos]+1) continue;
        if(edge[pos][i].cap == 0) continue;
        LL curflow = maxflow(nx,min(bcap,edge[pos][i].cap));
        if(curflow == 0) continue;
        edge[pos][i].cap -= curflow;
        edge[nx][edge[pos][i].backidx].cap += curflow;
        return curflow;
    }
    return 0;
}

int main(){
    cin >> n >> m;
    memset(dist,INFMEM,sizeof(dist));
    for(int i = 1;i <= m;i++){
    	LL u,v; cin >> u >> v;
    	dist[u][v] = 1;
	}
    for(int i = 1;i <= n;i++) dist[i][i] = 0;
	for(int k = 1;k <= n;k++){
		for(int i = 1;i <= n;i++){
			for(int j = 1;j <= n;j++){
				dist[i][j] = min(dist[i][j],dist[i][k]+dist[k][j]);
			}
		}
	}
	cin >> ShipN >> BaseN >> DepM;
	for(int i = 1;i <= ShipN;i++){
		cin >> ship[i].pos >> ship[i].att >> ship[i].fuel >> ship[i].price;
        events.pb({ship[i].att,i,0});
	}
	for(int i = 1;i <= BaseN;i++){
		cin >> base[i].pos >> base[i].def >> base[i].price;
        events.pb({base[i].def,i,1});
	}
    sort(events.begin(),events.end());
	//Computing profit
    for(int i = 1;i <= n;i++) CurMaxgold[i] = -LINF;
    for(int i = 0;i < events.size();i++){
        LL curidx = events[i].idx;
        if(events[i].type == 1){
            CurMaxgold[base[curidx].pos] = max(CurMaxgold[base[curidx].pos],base[curidx].price);
        }else{
            LL u = ship[curidx].pos;
            ship[curidx].profit = -LINF;
            for(int j = 1;j <= n;j++){
                if(dist[u][j] <= ship[curidx].fuel){
                    //Can use this base
                    ship[curidx].profit = max(ship[curidx].profit,CurMaxgold[j]-ship[curidx].price);
                }
            }
        }
    }
    //Debugin here
    // for(int i = 1;i <= ShipN;i++){
    //     cout << "The ship " << i << " has profit " << ship[i].profit << endl;
    // }
    LL ans = 0;
    s = 0; e = ShipN+1;
    for(int i = 1;i <= ShipN;i++){
        if(ship[i].profit < 0){
            make_edge(i,e,abs(ship[i].profit),0);
        }else{
            ans += ship[i].profit;
            make_edge(s,i,ship[i].profit,0);
        }
    }
    for(int i = 1;i <= DepM;i++){
        LL u,v; cin >> u >> v;
        make_edge(u,v,LINF,0);
    }
    //Set S sama E jangan lupa
    while(1){
        memset(level,0,sizeof(level));
        memset(st,0,sizeof(st));
        level[s] = 1;
        antri.push({s,1});
        while(!antri.empty()){
            dta tmp = antri.front();
            antri.pop();
            bfs(tmp);
        }
        if(level[e] == 0) break;
        LL curflow;
        while(curflow = maxflow(s,LINF)) ans -= curflow;
    }
    printf("%lld\n",ans);
    return 0;

    return 0;
}

#include <bits/stdc++.h>
using namespace std;

#define ll long long

const int mxN=100, mxA=1e5;

namespace maxflow {
	const int maxnodes=mxA+5;
	int nodes = maxnodes, src, dest;
	int dist[maxnodes], q[maxnodes], work[maxnodes];
	struct Edge {
		int to, rev;
		ll f, cap;
	};
	vector<Edge> g[maxnodes];
	void addEdge(int s, int t, ll cap){
		Edge a = {t, g[t].size(), 0, cap};
		Edge b = {s, g[s].size(), cap, cap};
		g[s].push_back(a);
		g[t].push_back(b);
	}
	bool dinic_bfs() {
		fill(dist, dist + nodes, -1);
		dist[src] = 0;
		int qt = 0;
		q[qt++] = src;
		for (int qh = 0; qh < qt; qh++) {
			int u = q[qh];
			for (int j = 0; j < (int) g[u].size(); j++) {
				Edge &e = g[u][j];
				int v = e.to;
				if (dist[v] < 0 && e.f < e.cap) {
					dist[v] = dist[u] + 1;
					q[qt++] = v;
				}
			}
		}
		return dist[dest] >= 0;
	}
	ll dinic_dfs(int u, ll f) {
		if (u == dest)
			return f;
		for (int &i = work[u]; i < (int) g[u].size(); i++) {
			Edge &e = g[u][i];
			if (e.cap <= e.f) continue;
			int v = e.to;
			if (dist[v] == dist[u] + 1) {
				ll df = dinic_dfs(v, min(f, e.cap - e.f));
				if (df > 0) {
					e.f += df;
					g[v][e.rev].f -= df;
					return df;
				}
			}
		}
		return 0;
	}
	ll maxFlow(int _src, int _dest) {
		src = _src;
		dest = _dest;
		ll result = 0;
		while (dinic_bfs()) {
			fill(work, work + nodes, 0);
			while (ll delta = dinic_dfs(src, 1e18))
				result += delta;
		}
		return result;
	}
}

namespace closure {
	int c[mxA];
	ll a[mxA];
	vector<int> adj[mxA], adj2[mxA], st;
	bool vis[mxA];
	void dfs1(int u) {
		vis[u]=1;
		for(int v : adj[u])
			if(!vis[v])
				dfs1(v);
		st.push_back(u);
	}
	void dfs2(int u, int cu) {
		vis[u]=0;
		c[u]=cu;
		for(int v : adj2[u])
			if(vis[v])
				dfs2(v, cu);
	}
	ll solve(int s) {
		for(int i=0; i<s; ++i)
			if(!vis[i])
				dfs1(i);
		for(int i=0; i<s; ++i)
			for(int j : adj[i])
				adj2[j].push_back(i);
		for(int i=s-1; ~i; --i)
			if(vis[st[i]])
				dfs2(st[i], st[i]);
		ll a1=0;
		for(int i=0; i<s; ++i) {
			if(i^c[i])
				a[c[i]]+=a[i];
		}
		for(int i=0; i<s; ++i)
			if(i==c[i])
				a1+=max(a[i], 0ll);
		int source=s, sink=s+1;
		maxflow::nodes=s+2;
		for(int i=0; i<s; ++i) {
			if(i==c[i]) {
				if(a[i]>0)
					maxflow::addEdge(source, i, a[i]);
				else
					maxflow::addEdge(i, sink, -a[i]);
			}
		}
		for(int i=0; i<s; ++i)
			for(int j : adj[i])
				if(c[i]^c[j])
					maxflow::addEdge(c[i], c[j], 1e18);
		return a1-maxflow::maxFlow(source, sink);
	}
}

int n, m, d[mxN], s, b, k, ax[mxA], aa[mxA], af[mxA], bx[mxA], bd[mxA], bg[mxA], mg[mxN], pb[mxA];
ll ap[mxA];
vector<int> adj[mxN], va[mxN];

int main() {
	ios_base::sync_with_stdio(0);
	cin.tie(0);

	cin >> n >> m;
	for(int u, v; m--; ) {
		cin >> u >> v, --u, --v;
		adj[u].push_back(v);
		adj[v].push_back(u);
	}
	cin >> s >> b >> k;
	for(int i=0; i<s; ++i) {
		cin >> ax[i] >> aa[i] >> af[i] >> ap[i], --ax[i];
		ap[i]=-ap[i];
		va[ax[i]].push_back(i);
	}
	for(int i=0; i<b; ++i) {
		cin >> bx[i] >> bd[i] >> bg[i], --bx[i];
	}
	iota(pb, pb+b, 0);
	sort(pb, pb+b, [](const int &i, const int &j) {
		return bd[i]<bd[j];
	});
	for(int s=0; s<n; ++s) {
		d[s]=0;
		queue<int> qu;
		qu.push(s);
		while(qu.size()) {
			int u=qu.front();
			qu.pop();
			for(int v : adj[u]) {
				if(d[v]>d[u]+1) {
					d[v]=d[u]+1;
					qu.push(v);
				}
			}
		}
		memset(mg, -1, sizeof(mg));
		sort(va[s].begin(), va[s].end(), [](const int &i, const int &j) {
			return aa[i]<aa[j];
		});
		for(int i1=0, i2=0; i1<va[s].size()||i2<b; ) {
			if(i1<va[s].size()&&(i2>=b||aa[va[s][i1]]<bd[pb[i2]])) {
				int ca=-1;
				for(int j=0; j<=min(n-1, af[va[s][i1]]); ++j)
					ca=max(ca, mg[j]);
				if(ca>=0)
					ap[va[s][i1]]+=ca;
				else
					ap[va[s][i1]]=-1e14;
				++i1;
			} else {
				if(d[pb[i2]]<n)
					mg[d[bx[pb[i2]]]]=max(mg[d[bx[pb[i2]]]], bg[pb[i2]]);
				++i2;
			}
		}
	}
	for(int i=0; i<k; ++i) {
		int s1, s2;
		cin >> s1 >> s2, --s1, --s2;
		closure::adj[s1].push_back(s2);
	}
	for(int i=0; i<s; ++i) {
		closure::a[i]=ap[i];
	}
	cout << closure::solve(s);
}

#include <algorithm>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <cstdio>
#include <cstdlib>
#include <cctype>
#include <cmath>
#include <cstring>
#include <list>
#include <cassert>
#include <climits>
#include <bitset>
using namespace std;

#define PB push_back
#define MP make_pair
#define SZ(v) ((int)(v).size())
#define FOR(i,a,b) for(int i=(a);i<(b);++i)
#define REP(i,n) FOR(i,0,n)
#define FORE(i,a,b) for(int i=(a);i<=(b);++i)
#define REPE(i,n) FORE(i,0,n)
#define FORSZ(i,a,v) FOR(i,a,SZ(v))
#define REPSZ(i,v) REP(i,SZ(v))
typedef long long ll;
int gcd(int a,int b) { return b==0?a:gcd(b,a%b); }

const int MAXN=100;
const int MAXSHIP=100000;
const int MAXBASE=100000;
const int MAXDEP=1000;

const int MAXGN=2+MAXSHIP;
const int MAXGM=MAXSHIP+MAXDEP;

typedef struct MF {
	int n,m;
	int ghead[MAXGN],gnxt[2*MAXGM],gto[2*MAXGM]; ll gcap[2*MAXGM];
	void init(int _n) { n=_n,m=0; REP(i,n) ghead[i]=-1; }
	void addedge(int a,int b,ll c) { gnxt[2*m+0]=ghead[a],ghead[a]=2*m+0,gto[2*m+0]=b,gcap[2*m+0]=c; gnxt[2*m+1]=ghead[b],ghead[b]=2*m+1,gto[2*m+1]=a,gcap[2*m+1]=0; ++m; /*printf("%d->%d\n",a,b);*/ }
	int d[MAXGN];
	int q[MAXGN],qhead,qtail;
	int cur[MAXGN];
	ll dinic(int s,int t) {
		ll ret=0; int niter=0;
		while(true) {
			REP(i,n) d[i]=INT_MAX; qhead=qtail=0; d[s]=0,q[qhead++]=s;
			while(qtail<qhead&&d[t]==INT_MAX) { int at=q[qtail++];for(int x=ghead[at];x!=-1;x=gnxt[x]) { int to=gto[x]; if(gcap[x]==0||d[to]!=INT_MAX) continue; d[to]=d[at]+1; q[qhead++]=to; } }
			if(d[t]==INT_MAX) return ret;
			REP(i,n) cur[i]=ghead[i];
			ret+=dfs(s,t,LLONG_MAX); ++niter;
		}
	}
	ll dfs(int at,int t,ll rem) {
		ll ret=0; if(at==t) return rem;
		if(d[at]>=d[t]) return 0;
		for(;cur[at]!=-1;cur[at]=gnxt[cur[at]]) {
			int to=gto[cur[at]]; ll cap=gcap[cur[at]]; if(d[to]!=d[at]+1||cap==0) continue;
			ll now=dfs(to,t,min(cap,rem));
			rem-=now; ret+=now; if(gcap[cur[at]]!=LLONG_MAX) gcap[cur[at]]-=now; if(gcap[cur[at]^1]!=LLONG_MAX) gcap[cur[at]^1]+=now; if(rem==0) return ret;
		}
		return ret;
	}
} MF;
MF g;

struct Ship { int pos,attack,fuel,cost; };
struct Base { int pos,defense,gold; };
bool operator<(const Base &a,const Base &b) { if(a.gold!=b.gold) return a.gold>b.gold; return a.defense<b.defense; }

int n,m;
int d[MAXN][MAXN];
int nship,nbase,ndep;
Ship ship[MAXSHIP];
Base base[MAXBASE];
vector<int> dep[MAXSHIP];

vector<Base> opt[MAXN];
ll best[MAXSHIP];
vector<int> rdep[MAXSHIP];
bool alive[MAXSHIP];
int q[MAXSHIP],qhead,qtail;

int nid,sid,tid,shipid[MAXSHIP];

ll solve() {
	REP(i,nbase) opt[base[i].pos].PB(base[i]);
	REP(i,n) sort(opt[i].begin(),opt[i].end());
	REP(i,n) { int nsz=0; REPSZ(j,opt[i]) if(nsz==0||opt[i][j].defense<opt[i][nsz-1].defense) opt[i][nsz++]=opt[i][j]; opt[i].resize(nsz); }
	//REP(i,n) { printf("%d:",i+1); REPSZ(j,opt[i]) printf(" %d=%d",opt[i][j].defense,opt[i][j].gold); puts(""); }

	REP(i,nship) best[i]=LLONG_MIN;
	REP(i,nship) REP(j,n) if(d[ship[i].pos][j]<=ship[i].fuel&&SZ(opt[j])>0&&ship[i].attack>=opt[j].back().defense) {
		int l=-1,r=SZ(opt[j])-1;
		while(l+1<r) { int m=l+(r-l)/2; if(ship[i].attack>=opt[j][m].defense) r=m; else l=m; }
		best[i]=max(best[i],(ll)opt[j][r].gold-ship[i].cost);
	}
	//printf("best:"); REP(i,nship) printf(" %lld",best[i]); puts("");

	REP(i,nship) REPSZ(j,dep[i]) { int k=dep[i][j]; rdep[k].PB(i); }
	qhead=qtail=0; REP(i,nship) { alive[i]=best[i]!=LLONG_MIN; if(!alive[i]) q[qhead++]=i; }
	while(qtail<qhead) { int at=q[qtail++]; REPSZ(i,rdep[at]) { int to=rdep[at][i]; if(alive[to]) alive[to]=false,q[qhead++]=to; } }
	//printf("alive:"); REP(i,nship) printf(" %d",alive[i]?1:0); puts("");

	nid=0,sid=nid++,tid=nid++; REP(i,nship) if(!alive[i]) shipid[i]=-1; else shipid[i]=nid++;
	g.init(nid);
	ll sum=0;
	REP(i,nship) if(alive[i]) { if(best[i]>0) sum+=best[i],g.addedge(sid,shipid[i],best[i]); if(best[i]<0) g.addedge(shipid[i],tid,-best[i]); }
	REP(i,nship) REPSZ(j,dep[i]) { int k=dep[i][j]; if(!alive[i]) continue; assert(alive[k]); g.addedge(shipid[i],shipid[k],LLONG_MAX); }
	ll flow=g.dinic(sid,tid);
	return sum-flow;
}

void run() {
	scanf("%d%d",&n,&m);
	REP(i,n) REP(j,n) d[i][j]=i==j?0:INT_MAX;
	REP(i,m) { int a,b; scanf("%d%d",&a,&b); --a,--b; d[a][b]=min(d[a][b],1); d[b][a]=min(d[b][a],1); }
	REP(k,n) REP(i,n) REP(j,n) if(d[i][k]!=INT_MAX&&d[k][j]!=INT_MAX) d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
	scanf("%d%d%d",&nship,&nbase,&ndep);
	REP(i,nship) scanf("%d%d%d%d",&ship[i].pos,&ship[i].attack,&ship[i].fuel,&ship[i].cost),--ship[i].pos;
	REP(i,nbase) scanf("%d%d%d",&base[i].pos,&base[i].defense,&base[i].gold),--base[i].pos;
	REP(i,ndep) { int a,b; scanf("%d%d",&a,&b); --a,--b; dep[a].PB(b); }
	printf("%lld\n",solve());
}

int main() {
	run();
	return 0;
}

#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define ULL unsigned long long
#define mp make_pair
#define pb push_back
#define pii pair<int,int>
#define pll pair<LL,LL>
#define x first
#define y second
#define pi acos(-1)
#define sqr(x) ((x)*(x))
#define pdd pair<double,double>
#define MEMS(x) memset(x,-1,sizeof(x))
#define MEM(x) memset(x,0,sizeof(x))
#define less Less
vector<int> v[100005];
struct Dinic{
    static const int MXN = 250000;
    struct Edge{ LL v,f,re; Edge(LL a,LL b,LL c):v(a),f(b),re(c){}};
    int n,s,t,level[MXN];
    vector<Edge> E[MXN];
    void init(int _n, int _s, int _t){
        n = _n; s = _s; t = _t;
        for (int i=0; i<=n; i++) E[i].clear();
    }
    void add_edge(int u, int v, LL f){
        E[u].pb(Edge(v,f,E[v].size()));
        E[v].pb(Edge(u,0,E[u].size()-1));//direct
     //   printf("%d %d %d\n",u,v,f);
    }
    bool BFS(){
        MEMS(level);
        queue<int> que;
        que.push(s);
        level[s] = 0;
        while (!que.empty()){
            int u = que.front(); que.pop();
            for (auto it : E[u]){
                if (it.f > 0 && level[it.v] == -1){
                    level[it.v] = level[u]+1;
                    que.push(it.v);
                }
            }
        }
        return level[t] != -1;
    }
    LL DFS(int u, LL nf){
        if (u == t) return nf;
        LL res = 0;
        for (auto &it : E[u]){
            if (it.f > 0 && level[it.v] == level[u]+1){
                LL tf = DFS(it.v, min(nf,(LL)it.f));
                res += tf; nf -= tf; it.f -= tf;
                E[it.v][it.re].f += tf;
                if (nf == 0) return res;
            }
        }
        if (!res) level[u] = -1;
        return res;
    }
    LL flow(LL res=0){
        while ( BFS() )
        res += DFS(s,1e18);
        return res;
    }
}flow;
int vis[100005],s;
void go(int x,int t){
    for(auto it:v[x]){
        if(vis[it]!=t){
            flow.add_edge(t,it+s,1e18);
            vis[it]=t;
            go(it,t);
        }
    }
}
int main(){
    int n,m;
    scanf("%d %d",&n,&m);
    int dis[105][105];
    for(int i = 1;i<=n;i++){
        for(int j = 1;j<=n;j++)
            dis[i][j]=1e9;
        dis[i][i]=0;
    }
    for(int i = 0;i<m;i++){
        int x,y;
        scanf("%d %d",&x,&y);
        dis[x][y]=dis[y][x]=1;
    }
    for(int i = 1;i<=n;i++){
        for(int j = 1;j<=n;j++){
            for(int k = 1;k<=n;k++){
                dis[j][k]=min(dis[j][i]+dis[i][k],dis[j][k]);
            }
        }
    }
    int B,k;
    scanf("%d %d %d",&s,&B,&k);
    int x[100005],a[100005],f[100005],p[100005];
    vector<pii> base[105];
    for(int i = 1;i<=s;i++){
        scanf("%d %d %d %d",&x[i],&a[i],&f[i],&p[i]);
    }
    for(int i = 0;i<B;i++){
        int a,b,c;
        scanf("%d %d %d",&a,&b,&c);
        base[a].pb(mp(b,c));
    }
    for(int i = 1;i<=n;i++){
    //    base[i].pb(mp(0,0));
        sort(base[i].begin(),base[i].end());
        vector<pii> tmp=base[i];
        base[i].clear();
        base[i].pb(mp(0,0));
        for(auto it:tmp){
            if(it.y>base[i].back().y){
                base[i].pb(it);
            }
        }
       // for(auto it:base[i])
       // printf("%d %d ",it.x,it.y);
       // printf("\n");
    }
    int val[100005];
    for(int i = 1;i<=s;i++){
        val[i]=-p[i];
        for(int j = 1;j<=n;j++){
            if(dis[x[i]][j]<=f[i]){
              //  printf("%d %d\n",i,j);
                val[i]=max(val[i],(lower_bound(base[j].begin(),base[j].end(),mp(a[i],1000000009))-1)->y-p[i]);
                //printf("%d\n",(lower_bound(base[i].begin(),base[i].end(),mp(a[i],1000000000))-1)->y)
            }
        }
     //   printf("%d\n",val[i]);
    }
    for(int i = 0;i<k;i++){
        int a,b;
        scanf("%d %d",&a,&b);
        v[b].pb(a);
    }
    flow.init(2*s+10,0,2*s+1);
    LL ans=0;
    for(int i =1;i<=s;i++){
        if(val[i]>0){
            ans+=val[i];
            flow.add_edge(i+s,2*s+1,val[i]);
        }
        else if(val[i]<0){
            if(val[i]==-p[i])
            flow.add_edge(0,i,1e18);
            else
            flow.add_edge(0,i,-val[i]);
            go(i,i);
        }

    }
  //  printf("%lld\n",ans);
    printf("%lld\n",ans-flow.flow());
}

#include <bits/stdc++.h>
using namespace std;
const int INF = 1e8;
const int maxn = 100015;
const int maxm = 1000005;
int g[105][105];
int num[maxn];
int cnt;
void floyed(int n){
    for(int k = 1; k <= n; k++){
        for(int i = 1; i <= n; i++){
            for(int j = 1; j <= n; j++){
                g[i][j] = min(g[i][j], g[i][k]+g[k][j]);
            }
        }
    }
};
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
    while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
struct Edge{
    int to,next,cap,flow;
}edge[maxm];
int tol,head[maxn];
void init()
{
    tol=2;
    memset(head,-1,sizeof(head));
}
void addedge(int u,int v,int w,int rw=0)
{
    edge[tol].to=v;edge[tol].cap=w;edge[tol].flow=0;
    edge[tol].next=head[u];head[u]=tol++;
    edge[tol].to=u;edge[tol].cap=rw;edge[tol].flow=0;
    edge[tol].next=head[v];head[v]=tol++;
}
int Q[maxn];
int dep[maxn],cur[maxn],sta[maxn];
bool bfs(int s,int t,int n)
{
    int front=0,tail=0;
    memset(dep,-1,sizeof(dep[0])*(n+1));
    dep[s]=0;
    Q[tail++]=s;
    while(front<tail){
        int u=Q[front++];
        for(int i=head[u];i!=-1;i=edge[i].next){
            int v=edge[i].to;
            if(edge[i].cap>edge[i].flow&&dep[v]==-1){
                dep[v]=dep[u]+1;
                if(v==t){
                    return true;
                }
                Q[tail++]=v;
            }
        }
    }
    return false;
}
int dinic(int s,int t,int n)
{
    int maxflow=0;
    while(bfs(s,t,n)){
        for(int i=0;i<n;i++){
            cur[i]=head[i];
        }
        int u=s,tail=0;
        while(cur[s]!=-1){
            if(u==t){
                int tp=INF;
                for(int i=tail-1;i>=0;i--){
                    tp=min(tp,edge[sta[i]].cap-edge[sta[i]].flow);
                }
                maxflow+=tp;
                for(int i=tail-1;i>=0;i--){
                    edge[sta[i]].flow+=tp;
                    edge[sta[i]^1].flow-=tp;
                    if(edge[sta[i]].cap-edge[sta[i]].flow==0){
                        tail=i;
                    }
                }
                u=edge[sta[tail]^1].to;
            }else if(cur[u]!=-1&&edge[cur[u]].cap>edge[cur[u]].flow&&dep[u]+1==dep[edge[cur[u]].to]){
                sta[tail++]=cur[u];
                u=edge[cur[u]].to;
            }else{
                while(u!=s&&cur[u]==-1){
                    u=edge[sta[--tail]^1].to;
                }
                cur[u]=edge[cur[u]].next;
            }
        }
    }
    return maxflow;
}
//vector<int>fuck[100005];
int fuckacm[100005];
int in[maxn], out[maxn], shipos[maxn], atk[maxn], f[maxn], p[maxn], baspos[maxn], d[maxn], gold[maxn], val[maxn];
bool svis[maxn];
int main(){
    int n, m, u, v, s, b, k;
    n = read(), m = read();
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n; j++){
            if(i==j) g[i][j] = 0;
            else g[i][j] = g[j][i] = INF;
        }
    }
    for(int i = 1; i <= m; i++){
        u = read(), v = read();
        g[u][v] = g[v][u] = 1;
    }
    floyed(n);
    s = read(), b = read(), k = read();
    for(int i = 1; i <= s; i++){
        shipos[i] = read(), atk[i] = read(), f[i] = read(), p[i] = read();
    }
    for(int i = 1; i <= b; i++){
        baspos[i] = read(), d[i] = read(), gold[i] = read();
    }
    for(int i = 1; i <= k; i++){
        int tmp1, tmp2;
        tmp1 = read(), tmp2 = read();
        fuckacm[tmp1] = tmp2;
        in[tmp2]++, out[tmp1]++;
    }
    for(int i = 1; i <= s; i++){
        int tmpgold = 0;
        for(int j = 1; j <= b; j++){
            if(tmpgold >= gold[j]) continue;
            if(g[shipos[i]][baspos[j]] <= f[i] && atk[i] >= d[j]){
                tmpgold = gold[j];
            }
        }
        val[i] = tmpgold - p[i];
    }
    long long ans = 0;
    for(int i = 1; i <= s; i++){
        if(in[i] == 0 && out[i] > 0){
            if(val[i] <= 0){
                svis[i] = true;
            }
        }
        if(in[i] == 0 && out[i] == 0 && val[i]>0){
            ans += val[i];
            svis[i] = true;
        }
        if(in[i] == 0 && out[i] == 0 && val[i] < 0){
            svis[i] = true;
        }
    }
    int S = 2015+1, T = S+1;
    init();
    for(int i = 1; i <= s; i++){
        if(!svis[i]){
            if(val[i] > 0){
                num[i] = ++cnt;
                addedge(S, cnt, val[i]);
                ans += val[i];
            }
            else{
                num[i] = ++cnt;
                addedge(cnt, T, -val[i]);
            }
        }
    }
    for(int i = 1; i <= s; i++){
        if(!svis[i] && val[i] > 0)
            addedge(num[i], num[fuckacm[i]], INF);
    }
    ans -= dinic(S, T, T+1);
    cout << ans;
    return 0;
}

#pragma GCC optimize("O3")
#include <bits/stdc++.h>

using namespace std;

#define sim template<class c
#define ris return *this
#define dor > debug & operator<<
#define eni(x) sim>typename \
  enable_if<sizeof dud<c>(0) x 1, debug&>::type operator<<(c i) {
sim> struct rge { c b, e; };
sim> rge<c> range(c i, c j) { return rge<c>{i, j}; }
sim> auto dud(c*x) -> decltype(cerr<<*x, 0);
sim> char dud(...);
struct debug {
#ifdef LOCAL
~debug() { cerr << endl; }
eni(!=) cerr << boolalpha << i; ris; }
eni(==) ris << range(begin(i), end(i)); }
sim, class b dor (pair<b,c> d) {
  ris<<"("<<d.first<<", "<<d.second<<")";
}
sim dor(rge<c> d) {
  *this<<"[";
  for (auto it = d.b; it != d.e; ++it)
    *this << ", " + 2 * (it == d.b) << *it;
  ris <<" ]";
}
#else
sim dor(const c&) { ris; }
#endif
};
#define imie(...) " [" << #__VA_ARGS__ ": " << (__VA_ARGS__) << "] "

using ll = long long;
#define int ll
#define PB push_back
#define MP make_pair
#define PII pair<int, int>
#define SZ(x) ((int)(x).size())
#define VI vector<int>
using pii = pair<int, int>;
using pll = pair<ll, ll>;
using vi = vector<int>;
using vll = vector<ll>;

struct Dinic {
  struct Edge { int v, c, inv; };

public:
  Dinic() : n(-1) {}
  void AddEdge(int a, int b, int cap, int bi_dir) {
    debug() << imie(a) << imie(b) << imie(cap);
    if (n < max(a, b)) { n = max(n, max(a, b)); ResizeVectors(); }
    e_orig[a].PB(Edge{b, cap, SZ(e_orig[b])});
    e_orig[b].PB(Edge{a, bi_dir * cap, SZ(e_orig[a]) - 1});
  }
  int MaxFlow(int s, int t) {
    if (t > n || s > n) { n = max(s, t); ResizeVectors(); }
    e = e_orig; int result = 0;
    while (Bfs(s, t)) {
      fill_n(beg.begin(), n + 1, 0);
      result += Dfs(s, t, kInf);
      assert(result < kInf);
    }
    return result;
  }

  int n;
  vector<vector<Edge>> e_orig, e;
  VI dis, beg;

  bool Bfs(int s, int t) {
    fill_n(dis.begin(), n + 1, n + 1);
    dis[s] = 0; VI que{s};
    for (int i = 0; i < SZ(que); ++i) {
      int v = que[i];
      for (auto edge : e[v]) {
        int nei = edge.v;
        if (edge.c && dis[nei] > dis[v] + 1) {
          dis[nei] = dis[v] + 1;
          que.PB(nei);
          if (nei == t) { return true; }
        }
      }
    }
    return false;
  }

  int Dfs(int v, int t, int min_cap) {
    int result = 0;
    if (v == t || !min_cap) { return min_cap; }
    for (int &i = beg[v]; i < SZ(e[v]); ++i) {
      int nei = e[v][i].v, c = e[v][i].c;
      if (dis[nei] == dis[v] + 1 && c > 0) {
        int flow_here = Dfs(nei, t, min(min_cap, c));
        result += flow_here;
        min_cap -= flow_here;
        e[v][i].c -= flow_here;
        e[nei][e[v][i].inv].c += flow_here;
      }
      if (min_cap == 0) { break; }
    }
    return result;
  }

  void ResizeVectors() {
    e_orig.resize(n + 2);
    beg.resize(n + 2);
    dis.resize(n + 2);
  }

  static const int kInf = 1e18;
};

const int MaxN = 105;
const int MaxItems = 1e5 + 100;

int n, m;
vi adj[MaxN];
int s, b, k, h;
int dist[MaxN][MaxN];
vector<pii> at_vert[MaxN];

int sp_loc[MaxItems], sp_atk[MaxItems], sp_fuel[MaxItems], sp_price[MaxItems];
int bs_loc[MaxItems], bs_def[MaxItems], bs_gold[MaxItems];

vi dep_adj[MaxItems];
bool any_dep[MaxItems];
int dep_idx[MaxItems];

int32_t main() {
  scanf("%lld%lld", &n, &m);
  for (int i = 0; i < n; ++i) {
    for (int j = 0; j < n; ++j) {
      dist[i][j] = 2e9;
    }
    dist[i][i] = 0;
  }

  for (int i = 0; i < m; ++i) {
    int u, v;
    scanf("%lld%lld", &u, &v);
    adj[u].push_back(v);
    adj[v].push_back(u);
    if (u != v) {
      dist[u][v] = dist[v][u] = 1;
    }
  }

  for (int k = 1; k <= n; ++k) {
    for (int i = 1; i <= n; ++i) {
      for (int j = 1; j <= n; ++j) {
        dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
      }
    }
  }

  scanf("%lld%lld%lld", &s, &b, &k);

  for (int i = 0; i < s; ++i) {
    scanf("%lld%lld%lld%lld", &sp_loc[i], &sp_atk[i], &sp_fuel[i], &sp_price[i]);
  }
  for (int i = 0; i < b; ++i) {
    scanf("%lld%lld%lld", &bs_loc[i], &bs_def[i], &bs_gold[i]);
    at_vert[bs_loc[i]].emplace_back(bs_def[i], bs_gold[i]);
  }

  for (int v = 1; v <= n; ++v) {
    auto &X = at_vert[v];
    sort(X.begin(), X.end());

    const int sz = X.size();
    int cur_max = -1;
    int ptr = 0;
    for (int i = 0; i < sz; ++i) {
      if (X[i].second <= cur_max) { continue; }
      X[ptr++] = X[i];
      cur_max = X[i].second;
    }
    X.resize(ptr);

    debug() << imie(v) << imie(X);
  }

  const int kSmallInf = 2e9;
  const ll kLargeInf = 2e16;

  vll sp_best(s, -kLargeInf);
  for (int i = 0; i < s; ++i) {
    for (int v = 1; v <= n; ++v) {
      if (sp_fuel[i] < dist[sp_loc[i]][v]) { continue; }
      const int atk = sp_atk[i];
      auto iter =
        lower_bound(at_vert[v].begin(), at_vert[v].end(),
                    pii(atk, kSmallInf));
      if (iter == at_vert[v].begin()) {
        continue;
      } else {
        int bnd = prev(iter)->second;
        sp_best[i] = max(sp_best[i], (ll)bnd - sp_price[i]);
      }
    }
    debug() << imie(i) << imie(sp_best[i]);
  }

  for (int i = 0; i < k; ++i) {
    int u, v;
    scanf("%lld%lld", &u, &v);
    --u; --v;
    any_dep[u] = any_dep[v] = true;
    dep_adj[u].PB(v);
  }

  ll ans = 0;
  int curidx = 0;
  for (int i = 0; i < s; ++i) {
    if (!any_dep[i] && sp_best[i] >= 0) {
      ans += sp_best[i];
    }
    if (any_dep[i]) {
      dep_idx[i] = curidx++;
    }
  }

  Dinic dinic;
  const int source = curidx;
  const int sink = source + 1;

  debug() << imie(source) << imie(sink);

  for (int i = 0; i < s; ++i) {
    if (!any_dep[i]) { continue; }
    if (sp_best[i] >= 0) {
      dinic.AddEdge(source, dep_idx[i], sp_best[i], 0);
      ans += sp_best[i];
    } else {
      dinic.AddEdge(dep_idx[i], sink, -sp_best[i], 0);
    }

    for (int j : dep_adj[i]) {
      dinic.AddEdge(dep_idx[i], dep_idx[j], kLargeInf, 0);
    }
  }

  const ll flow = dinic.MaxFlow(source, sink);
  ans -= flow;
  assert(ans >= 0);

  printf("%lld\n", ans);

}

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int mod=1e9+7;
const int maxm=100+10;
const int maxn=3e5+10;
const int N=1e5+10;
const int inf=0x3f3f3f3f;
namespace io {
    const int SIZE = (1 << 21) + 1;
    char ibuf[SIZE], *iS, *iT, obuf[SIZE], *oS = obuf, *oT = oS + SIZE - 1, c, qu[55]; int f, qr;
    // getchar
    #define gc() (iS == iT ? (iT = (iS = ibuf) + fread (ibuf, 1, SIZE, stdin), (iS == iT ? EOF : *iS ++)) : *iS ++)
    // print the remaining part
    inline void flush () {
        fwrite (obuf, 1, oS - obuf, stdout);
        oS = obuf;
    }
    // putchar
    inline void putc (char x) {
        *oS ++ = x;
        if (oS == oT) flush ();
    }
    template<typename A>
    inline bool read (A &x) {
        for (f = 1, c = gc(); c < '0' || c > '9'; c = gc()) if (c == '-') f = -1;else if(c==EOF)return 0;
        for (x = 0; c <= '9' && c >= '0'; c = gc()) x = x * 10 + (c & 15); x *= f;
        return 1;
    }
    inline bool read (char &x) {
        while((x=gc())==' '||x=='\n' || x=='\r');
        return x!=EOF;
    }
    inline bool read(char *x){
        while((*x=gc())=='\n' || *x==' '||*x=='\r');
        if(*x==EOF)return 0;
        while(!(*x=='\n'||*x==' '||*x=='\r'||*x==EOF))*(++x)=gc();
        *x=0;
        return 1;
    }
    template<typename A,typename ...B>
    inline bool read(A &x,B &...y){
        return read(x)&&read(y...);
    }
    template<typename A>
    inline bool write (A x) {
        if (!x) putc ('0'); if (x < 0) putc ('-'), x = -x;
        while (x) qu[++ qr] = x % 10 + '0',  x /= 10;
        while (qr) putc (qu[qr --]);
        return 0;
    }
    inline bool write (char x) {
        putc(x);
        return 0;
    }
    inline bool write(const char *x){
        while(*x){putc(*x);++x;}
        return 0;
    }
    inline bool write(char *x){
        while(*x){putc(*x);++x;}
        return 0;
    }
    template<typename A,typename ...B>
    inline bool write(A x,B ...y){
        return write(x)||write(y...);
    }
    //no need to call flush at the end manually!
    struct Flusher_ {~Flusher_(){flush();}}io_flusher_;
}
using io :: read;
using io :: putc;
using io :: write;
int dis[maxm][maxm];
map<int,int> mp;
struct base{
	int def,gold,mmax;
	friend bool operator<(base a,base b)
	{
		return a.def<b.def;
	}
};
struct ship{
	int x,att,fuel,pri;
}a[N];
vector<base> v[maxm];
int val[N];
int s,t;
int now[N],dep[N],head[N];
struct edge{
	int v,w,nxt;
}e[maxn];
int ecnt;
void addedge(int u,int v,int w)
{
	e[ecnt]={v,w,head[u]};
	head[u]=ecnt++;
	e[ecnt]={u,0,head[v]};
	head[v]=ecnt++;
}
int bfs()//重新建图，按层次建图
{
    queue<int> q;
    while(!q.empty())
        q.pop();
    for(int i=s;i<=t;i++)
    {
    	dep[i]=-1;
    	now[i]=-1; //now[i]表示i的当前弧
    }
    dep[s] = 0; //dep为层次
    q.push(s);
    now[s]=head[s];
    while(!q.empty()){
        int u = q.front();
        q.pop();
        for(int i=head[u]; i!=-1; i=e[i].nxt){
        	int v=e[i].v;
            if(e[i].w > 0 && dep[v] == -1){//如果可以到达且还没有访问，可以到达的条件是剩余容量大于0，没有访问的条件是当前层数还未知
                dep[v] = dep[u] + 1;
                now[v]=head[v];
                q.push(v);
            }
        }
    }
    return dep[t] != -1;
}
int dfs(int u, int mi)//查找路径上的最小流量
{
    if(mi==0||u == t)
        return mi;
    int tmp,sum=0;
    for(int i=now[u]; i!=-1&&mi; i=e[i].nxt){
    	now[u]=i; //当前弧优化
    	int v=e[i].v;
        if(e[i].w > 0 && dep[v] == dep[u] + 1){
			tmp = dfs(v, min(mi, e[i].w));
            e[i].w -= tmp;
            e[i^1].w += tmp;
            sum+=tmp; //一次增广跑多条路，sum为流量总和
            mi-=tmp; //用掉了tmp
            if(!mi) break;
        }
    }
    return sum;
}
ll dinic()
{
    ll ans = 0;
    while(bfs()){
        ans+=dfs(s,inf);
    }
    return ans;
}
int main()
{
	memset(head,-1,sizeof(head));
	memset(dis,0x3f,sizeof(dis));
	int n,m;
	read(n,m);
	for(int i=1;i<=n;i++) dis[i][i]=0;
	for(int i=1;i<=m;i++)
	{
		int u,v;
		read(u,v);
		dis[u][v]=dis[v][u]=1;
	}
	for(int k=1;k<=n;k++)
		for(int i=1;i<=n;i++)
			for(int j=1;j<=n;j++)
				dis[i][j]=min(dis[i][k]+dis[k][j],dis[i][j]);
	int snum,bnum,k;
	read(snum,bnum,k);
	//assert(bnum<=n);
	for(int i=1;i<=snum;i++)
	{
		int x,att,fu,pri;
		read(x,att,fu,pri);
		a[i]={x,att,fu,pri};
	}
	for(int i=1;i<=bnum;i++)
	{
		int x,def,gol;
		read(x,def,gol);
		//assert((!mp[x])||mp[x]==def);
		//b[x]={def,gol};
		//mp[x]=def;
		v[x].push_back({def,gol,gol});
	}
	for(int i=1;i<=n;i++)
	{
		sort(v[i].begin(),v[i].end());
		for(int j=1;j<v[i].size();j++) v[i][j].mmax=max(v[i][j].gold,v[i][j-1].mmax);
	}
	for(int i=1;i<=snum;i++) val[i]=-inf;
	for(int i=1;i<=snum;i++)
	{
		for(int j=1;j<=n;j++)
		{
			if(a[i].fuel>=dis[a[i].x][j])
			{
				//val[i]=max(val[i],b[j].gold-a[i].pri);
				//int pos=v[a[i].x].lower_bound({a[i].att,inf,0})-v[a[i].x].begin();
				int l=0,r=v[j].size()-1,pos=-1;
				while(l<=r)
				{
					int mid=l+r>>1;
					if(v[j][mid].def<=a[i].att)
					{
						l=mid+1,pos=mid;
					}
					else r=mid-1;
				}
				if(pos<0) continue;
				val[i]=max(val[i],v[j][pos].mmax-a[i].pri);
			}
		}
	}
	s=0,t=snum+1;
	for(int i=1;i<=k;i++)
	{
		int u,v;
		read(u,v);
		addedge(v,u,inf);
	}
	ll tot=0;
	for(int i=1;i<=snum;i++)
	{
		//printf("val[%d]=%d\n",i,val[i]);
		if(val[i]<=-inf) continue;
		if(val[i]>=0)
		{
			tot+=val[i];
			addedge(i,t,val[i]);
		}
		if(val[i]<0) addedge(s,i,-val[i]);
	}
	tot-=dinic();
	printf("%lld\n",tot);
	return 0;
}

//~ while (clock()<=69*CLOCKS_PER_SEC)
//~ #pragma comment(linker, "/stack:200000000")
#pragma GCC optimize("O3")
//~ #pragma GCC optimize("Ofast")
//~ #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
//~ #pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

using namespace __gnu_pbds;
using namespace std;

template <typename T>
using ordered_set =
    tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;

#define sim template < class c
#define ris return * this
#define dor > debug & operator <<
#define eni(x) sim > typename \
  enable_if<sizeof dud<c>(0) x 1, debug&>::type operator<<(c i) {
sim > struct rge { c b, e; };
sim > rge<c> range(c i, c j) { return rge<c>{i, j}; }
sim > auto dud(c* x) -> decltype(cerr << *x, 0);
sim > char dud(...);
struct debug {
#ifdef LOCAL
~debug() { cerr << endl; }
eni(!=) cerr << boolalpha << i; ris; }
eni(==) ris << range(begin(i), end(i)); }
sim, class b dor(pair < b, c > d) {
  ris << "(" << d.first << ", " << d.second << ")";
}
sim dor(rge<c> d) {
  *this << "[";
  for (auto it = d.b; it != d.e; ++it)
    *this << ", " + 2 * (it == d.b) << *it;
  ris << "]";
}
#else
sim dor(const c&) { ris; }
#endif
};
#define imie(...) " [" << #__VA_ARGS__ ": " << (__VA_ARGS__) << "] "

#define shandom_ruffle random_shuffle

using ll=long long;
using pii=pair<int,int>;
using pll=pair<ll,ll>;
using vi=vector<int>;
using vll=vector<ll>;
const int nax=1007;
const ll inf=1e15;

int n, m;

ll odl[nax][nax];

int s, b;
int k;
int g[nax*nax];
ll sil[nax*nax];
ll pal[nax*nax];
ll cen[nax*nax];

vector <pll> bazy[nax];

using T = long long;
struct Flow {
  struct E {
    int dest;
    T orig, *lim, *rev;
  };
  int zr, uj, n = 0;
  vector<unique_ptr<T>> ts;
  vector<vector<E>> graf;
  vector<int> ptr, odl;
  void vert(int v) {
    n = max(n, v + 1);
    graf.resize(n);
    ptr.resize(n);
    odl.resize(n);
  }
  bool iszero(T v) {
    return !v; // Zmienić dla doubli.
  }
  void bfs() {
    fill(odl.begin(), odl.end(), 0);
    vector<int> kol = {zr};
    odl[zr] = 1;
    for (int i = 0; i < (int) kol.size(); i++) {
      for (E& e : graf[kol[i]]) {
        if (!odl[e.dest] and !iszero(*e.lim)) {
          odl[e.dest] = odl[kol[i]] + 1;
          kol.push_back(e.dest);
        }
      }
    }
  }
  T dfs(int v, T lim) {
    if (v == uj) return lim;
    T ret = 0, wez;
    for (int& i = ptr[v]; i < (int) graf[v].size(); i++) {
      E& e = graf[v][i];
      if (odl[e.dest] == odl[v] + 1 and !iszero(*e.lim) and
          !iszero(wez = dfs(e.dest, min(*e.lim, lim)))) {
        ret += wez;
        *e.lim -= wez;
        *e.rev += wez;
        lim -= wez;
        if (iszero(lim)) break;
      }
    }
    return ret;
  }
  void add_edge(int u, int v, T lim, bool bi = false /* bidirectional? */) {
    vert(max(u, v));
    T *a = new T(lim), *b = new T(lim * bi);
    ts.emplace_back(a);
    ts.emplace_back(b);
    graf[u].push_back(E{v, lim,      a, b});
    graf[v].push_back(E{u, lim * bi, b, a});
  }
  T dinic(int zr_, int uj_) {
    zr = zr_; uj = uj_;
    vert(max(zr, uj));
    T ret = 0;
    while (true) {
      bfs();
      fill(ptr.begin(), ptr.end(), 0);
      const T sta = dfs(zr, numeric_limits<T>::max());  // Dla doubli można dać
      if (iszero(sta)) break;                           // infinity() zamiast
      ret += sta;                                       // max().
    }
    return ret;
  }
  vector<int> cut() {
    vector<int> ret;
    bfs();
    for (int i = 0; i < n; i++)
      if (odl[i])
        ret.push_back(i);
    return ret;
  }
  map<pair<int, int>, T> get_flowing() {  // Tam gdzie plynie 0 może nie być
    map<pair<int, int>, T> ret;           // krawędzi.
    for (int i = 0; i < n; i++)
      for (E& e : graf[i])
        if (*e.lim < e.orig)
          ret[make_pair(i, e.dest)] += e.orig - *e.lim;
    for (auto& i : ret) {
      const pair<int, int> rev{i.first.second, i.first.first};
      const T x = min(i.second, ret[rev]);
      i.second -= x;
      ret[rev] -= x;
    }
    return ret;
  }
};

ll best(int v, ll og)
{
	int bsa=0;
	int bsb=(int)bazy[v].size()-1;
	while(bsa<bsb)
	{
		int bss=(bsa+bsb+2)>>1;
		if (bazy[v][bss].second<=og)
			bsa=bss;
		else
			bsb=bss-1;
	}
	return bazy[v][bsa].first;
}

int main()
{
	scanf("%d%d", &n, &m);
	for (int i=1; i<=n; i++)
		for (int j=1; j<=n; j++)
			odl[i][j]=(i!=j)*inf;
	for (int i=1; i<=m; i++)
	{
		int a, b;
		scanf("%d%d", &a, &b);
		if (a!=b)
			odl[a][b]=odl[b][a]=1;
	}
	for (int k=1; k<=n; k++)
		for (int i=1; i<=n; i++)
			for (int j=1; j<=n; j++)
				odl[i][j]=min(odl[i][j], odl[i][k]+odl[k][j]);
	scanf("%d%d%d", &s, &b, &k);
	for (int i=1; i<=s; i++)
		scanf("%d%lld%lld%lld", &g[i], &sil[i], &pal[i], &cen[i]);
	for (int i=1; i<=b; i++)
	{
		int x, y, z;
		scanf("%d%d%d", &x, &y, &z);
		bazy[x].push_back({z, -y});
	}
	for (int i=1; i<=n; i++)
	{
		bazy[i].push_back({0, 0});
		sort(bazy[i].begin(), bazy[i].end());
		auto pom=bazy[i];
		bazy[i].clear();
		for (pll j : pom)
		{
			j.second*=-1;
			while(!bazy[i].empty() && bazy[i].back().second>=j.second)
				bazy[i].pop_back();
			bazy[i].push_back(j);
		}
		//~ debug() << i << " " << bazy[i];
	}
	for (int i=1; i<=s; i++)
	{
		ll x=-inf;
		for (int j=1; j<=n; j++)
			if (pal[i]>=odl[g[i]][j])
				x=max(x, best(j, sil[i]));
		cen[i]=x-cen[i];
	}
	ll wyn=0;
	Flow janusz;
	for (int i=1; i<=s; i++)
	{
		if (cen[i]>=0)
		{
			wyn+=cen[i];
			janusz.add_edge(0, i, cen[i]);
		}
		else
		{
			janusz.add_edge(i, s+1, -cen[i]);
		}
	}
	for (int i=1; i<=k; i++)
	{
		int a, b;
		scanf("%d%d", &a, &b);
		//~ debug() << imie(a);
		//~ debug() << imie(b);
		janusz.add_edge(a, b, inf);
	}
	//~ debug() << imie(wyn);
	//~ debug() << imie(range(cen+1, cen+1+s));
	printf("%lld\n", wyn-janusz.dinic(0, s+1));
	return 0;
}

#include <bits/stdc++.h>
#define db(x) cout << (x) << '\n';
using namespace std;
typedef long long ll;
typedef pair<ll,ll> pii;
#define MAXN 105
#define oo2 ((ll)(1e9+7))
#define MAXM 100005

ll d[MAXN][MAXN];
vector<pii> bs[MAXN];
ll mbs[MAXN][MAXM],pl[MAXM],pp[MAXM][4];

template<typename flow_type>
struct dinic
{
	struct edge
	{
		size_t src, dst, rev;
		flow_type flow, cap;
	};

	int n;
	vector<vector<edge>> adj;

	dinic(int n) : n(n), adj(n), level(n), q(n), it(n) {}

	void add_edge(size_t src, size_t dst, flow_type cap, flow_type rcap = 0)
	{
		adj[src].push_back({src, dst, adj[dst].size(), 0, cap});
		if (src == dst) adj[src].back().rev++;
		adj[dst].push_back({dst, src, adj[src].size() - 1, 0, rcap});
	}

	vector<int> level, q, it;

	bool bfs(int source, int sink)
	{
		fill(level.begin(), level.end(), -1);
		for (int qf = level[q[0] = sink] = 0, qb = 1; qf < qb; ++qf)
		{
			sink = q[qf];
			for (edge &e : adj[sink])
			{
				edge &r = adj[e.dst][e.rev];
				if (r.flow < r.cap && level[e.dst] == -1)
					level[q[qb++] = e.dst] = 1 + level[sink];
			}
		}
		return level[source] != -1;
	}

	flow_type augment(int source, int sink, flow_type flow)
	{
		if (source == sink) return flow;
		for (; it[source] != adj[source].size(); ++it[source])
		{
			edge &e = adj[source][it[source]];
			if (e.flow < e.cap && level[e.dst] + 1 == level[source])
			{
				flow_type delta = augment(e.dst, sink,
								  min(flow, e.cap - e.flow));
				if (delta > 0)
				{
					e.flow += delta;
					adj[e.dst][e.rev].flow -= delta;
					return delta;
				}
			}
		}
		return 0;
	}

	flow_type max_flow(int source, int sink)
	{
		for (int u = 0; u < n; ++u)
			for (edge &e : adj[u]) e.flow = 0;
		flow_type flow = 0;
		flow_type oo = numeric_limits<flow_type>::max();

		while (bfs(source, sink))
		{
			fill(it.begin(), it.end(), 0);
			for (flow_type f; (f = augment(source, sink, oo)) > 0;)
				flow += f;

		} // level[u] = -1 => source side of min cut
		return flow;
	}
};

int main()
{
    ios_base::sync_with_stdio(0);
    cin.tie(0);

    ll n,m,u,v;
    cin >> n >> m;
    for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
            d[i][j]=oo2;
    for(ll i=0;i<m;i++)
    {
        cin >> u >> v;
        u--,v--;
        d[u][v]=d[v][u]=1;
    }

    for(int i=0;i<n;i++)
        d[i][i]=0;
    for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
            for(int k=0;k<n;k++)
                d[j][k]=min(d[j][k],d[j][i]+d[i][k]);

    ll s,b,k,gg,de;
    cin >> s >> b >> k;
    for(ll i=0;i<s;i++)
    {
        cin >> pp[i][0] >> pp[i][1] >> pp[i][2] >> pp[i][3];
        pp[i][0]--;
    }
    for(int i=0;i<b;i++)
    {
        cin >> u >> de >> gg;
        u--;
        bs[u].push_back(pii(de,gg));
    }

    for(int i=0;i<n;i++)
    {
        sort(bs[i].begin(),bs[i].end());
        ll ma=0;
        for(ll j=0;j<bs[i].size();j++)
        {
            ma=max(ma,bs[i][j].second);
            mbs[i][j]=ma;
        }
    }

    dinic<ll> g(2+s);
    ll s1=0;
    for(int i=0;i<s;i++)
    {
        ll ma=0;
        for(int j=0;j<n;j++)
        {
            if(d[j][pp[i][0]]>pp[i][2])
                continue;
            ll pos=upper_bound(bs[j].begin(),bs[j].end(),pii(pp[i][1],oo2))-bs[j].begin();
            if(pos)
                ma=max(ma,mbs[j][pos-1]);
        }
        pl[i]=ma-pp[i][3];
        if(pl[i]>0)
        {
            g.add_edge(0,i+1,pl[i]);
            s1+=pl[i];
        }
        if(pl[i]<0)
            g.add_edge(i+1,s+1,-pl[i]);
    }

    for(ll i=0;i<k;i++)
    {
        cin >> u >> v;
        g.add_edge(u,v,oo2*oo2);
    }

    db(s1-g.max_flow(0,s+1))

    return 0;
}

#include <bits/stdc++.h>

#define F first
#define S second
#define MP make_pair
#define PB push_back

using namespace std;

typedef long long ll;
typedef long double ld;

const int max_n = 111, inf = 1000111222;
const int max_v = 100011;

namespace flow {

struct edge {
    int v;
    long long res_cap;

    edge() {
    }

    edge(int v, long long res_cap): v(v), res_cap(res_cap) {
    }
};

vector<edge> all;
vector<int> g[max_v];

void add_edge(int u, int v, long long cap) {
    g[u].push_back(all.size());
    all.push_back({v, cap});
    g[v].push_back(all.size());
    all.push_back({u, 0});
}

int h[max_v], num[max_v];

bool bfs(int s, int t) {
    for (int i = 0; i <= t; ++i) {
        h[i] = -1;
    }
    h[s] = 0;
    queue<int> q;
    q.push(s);
    while (!q.empty()) {
        int v = q.front();
        q.pop();
        for (int id : g[v]) {
            if (all[id].res_cap && h[all[id].v] == -1) {
                h[all[id].v] = h[v] + 1;
                q.push(all[id].v);
            }
        }
    }
    return h[t] != -1;
}

int dfs(int v, int t, int f) {
    if (v == t) {
        return f;
    }
    for (int &i = num[v]; i < g[v].size(); ++i) {
        int id = g[v][i];
        const edge &e = all[id];
        if (h[v] + 1 == h[e.v] && e.res_cap) {
            int x = dfs(e.v, t, min(1LL * f, e.res_cap));
            if (x) {
                all[id].res_cap -= x;
                all[id ^ 1].res_cap += x;
                return x;
            }
        }
    }
    return 0;
}

long long dinic(int s, int t) {
    long long res = 0;
    while (bfs(s, t)) {
        memset(num, 0, sizeof(num));
        while (int x = dfs(s, t, 2 * inf)) {
            res += x;
        }
    }
    return res;
}

}

int n, m, dist[max_n][max_n];
int c1, c2, k;
int v1[max_v], attack[max_v], fluel[max_v], cost1[max_v], a[max_v];
int v2[max_v], defend[max_v], cost2[max_v], U[max_v], V[max_v], bad[max_v];
vector<pair<int, int>> all[max_n];
vector<int> rg[max_v];

void dfs(int v) {
    bad[v] = 1;
    for (int to : rg[v]) {
        if (!bad[to]) {
            dfs(to);
        }
    }
}

int main() {
    //freopen("input_b.txt", "r", stdin);
    //freopen("output.txt", "w", stdout);
    scanf("%d%d", &n, &m);
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < n; ++j) {
            dist[i][j] = inf;
        }
        dist[i][i] = 0;
    }
    while (m--) {
        int u, v;
        scanf("%d%d", &u, &v);
        --u;
        --v;
        dist[u][v] = 1;
        dist[v][u] = 1;
    }
    for (int k = 0; k < n; ++k) {
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < n; ++j) {
                dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
            }
        }
    }
    scanf("%d%d%d", &c1, &c2, &k);
    for (int i = 0; i < c1; ++i) {
        scanf("%d%d%d%d", &v1[i], &attack[i], &fluel[i], &cost1[i]);
        --v1[i];
    }
    for (int i = 0; i < c2; ++i) {
        scanf("%d%d%d", &v2[i], &defend[i], &cost2[i]);
        --v2[i];
        all[v2[i]].push_back({defend[i], cost2[i]});
    }
    for (int i = 0; i < n; ++i) {
        sort(all[i].begin(), all[i].end());
        for (int j = 1; j < all[i].size(); ++j) {
            all[i][j].second = max(all[i][j].second, all[i][j - 1].second);
        }
    }
    for (int i = 0; i < c1; ++i) {
        a[i] = -inf;
        for (int v = 0; v < n; ++v) {
            if (dist[v1[i]][v] > fluel[i]) {
                continue;
            }
            auto it = upper_bound(all[v].begin(), all[v].end(), make_pair(attack[i], inf));
            if (it != all[v].begin()) {
                --it;
                a[i] = max(a[i], it->second);
            }
        }
        if (a[i] != -inf) {
            a[i] -= cost1[i];
        } else {
            bad[i] = 1;
        }
        //cout << i << ": " << a[i] << endl;
    }
    int s = n, t = s + 1;
    long long ans = 0;
    for (int i = 0; i < c1; ++i) {
        if (!bad[i]) {
            flow::add_edge(s, i, inf + a[i]);
            flow::add_edge(i, t, inf);
            ans -= a[i] + inf;
        }
    }
    long long big_inf = 10001112LL * inf;
    for (int i = 0; i < k; ++i) {
        scanf("%d%d", &U[i], &V[i]);
        --U[i];
        --V[i];
        rg[V[i]].push_back(U[i]);
    }
    for (int i = 0; i < c1; ++i) {
        if (bad[i]) {
            dfs(i);
        }
    }
    for (int i = 0; i < k; ++i) {
        if (!bad[U[i]] && !bad[V[i]]) {
            flow::add_edge(U[i], V[i], big_inf);
        }
    }
    ans += flow::dinic(s, t);
    printf("%I64d\n", -ans);
    return 0;
}

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    ll n, m;
    cin >> n >> m;
    vector<vector<ll>> dist((size_t) n, vector<ll>((size_t) n, (ll) 1e16));
    for (ll i = 0; i < n; i++) {
        dist[i][i] = (ll) 0;
    }
    for (ll i = 0; i < m; i++) {
        ll u, v;
        cin >> u >> v;
        u--, v--;
        dist[u][v] = dist[v][u] = 0;
    }
    for (ll k = 0; k < n; k++) {
        for (ll i = 0; i < n; i++) {
            for (ll j = 0; j < n; j++) {
                dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
            }
        }
    }
    ll s, b, k;
    cin >> s >> b >> k;
    vector<tuple<ll, ll, ll, ll>> x((size_t) s);
    for (ll i = 0; i < s; i++) {
        cin >> get<0>(x[i]) >> get<1>(x[i]) >> get<2>(x[i]) >> get<3>(x[i]);
        get<0>(x[i])--;
    }
    vector<tuple<ll, ll, ll>> y((size_t) b);
    for (ll i = 0; i < b; i++) {
        cin >> get<0>(y[i]) >> get<1>(y[i]) >> get<2>(y[i]);
        get<0>(y[i])--;
    }
    vector<map<ll, ll>> bases((size_t) n);
    for (ll i = 0; i < b; i++) {
        bases[get<0>(y[i])][get<1>(y[i])] = get<2>(y[i]);
    }
    for (ll i = 0; i < n; i++) {
        for (auto j = bases[i].begin(); j != bases[i].end();) {
            if (j == bases[i].begin() || j->second > prev(j)->second) {
                j++;
            } else {
                j = bases[i].erase(j);
            }
        }
    }
    vector<ll> damages((size_t) s, (ll) -1e16);
    for (ll i = 0; i < s; i++) {
        for (ll j = 0; j < n; j++) {
            if (get<2>(x[i]) >= dist[get<0>(x[i])][j]) {
                auto it = bases[j].upper_bound(get<1>(x[i]));
                if (it != bases[j].begin()) {
                    damages[i] = max(damages[i], prev(it)->second - get<3>(x[i]));
                }
            }
        }
    }
    vector<vector<ll>> init_adj((size_t) s), init_adj_rev((size_t) s);
    vector<vector<pair<ll, ll>>> adj((size_t) s + 2);
    vector<map<ll, ll>> flows((size_t) s + 2);
    auto add_edge = [&](ll u, ll v, ll w) {
        adj[u].emplace_back(v, w);
        adj[v].emplace_back(u, 0);
        flows[u][v] = 0;
        flows[v][u] = 0;
    };
    for (ll i = 0; i < k; i++) {
        ll u, v;
        cin >> u >> v;
        u--, v--;
        if (u != v) {
            init_adj[u].push_back(v);
            init_adj_rev[v].push_back(u);
            add_edge(u, v, (ll) 1e16);
        }
    }
    ll o = 0;
    for (ll u = 0; u < s; u++) {
        if (damages[u] > 0) {
            if (!init_adj[u].empty()) {
                add_edge(s, u, damages[u]);
            } else {
                o += damages[u];
            }
        } else {
            if (!init_adj_rev[u].empty()) {
                add_edge(u, s + 1, -damages[u]);
            }
        }
    }
    vector<bool> visited;
    vector<ll> path;
    function<ll(ll)> visit = [&](ll u) {
        if (!visited[u]) {
            visited[u] = true;
            path.push_back(u);
            if (u == s + 1) {
                return (ll) 1e24;
            } else {
                for (auto[v, w] : adj[u]) {
                    if (w - flows[u][v] > 0) {
                        ll a = visit(v);
                        if (a > 0) {
                            return min(w - flows[u][v], a);
                        }
                    }
                }
            }
            path.pop_back();
        }
        return (ll) 0;
    };
    while (true) {
        visited.assign((ll) s + 2, false);
        path.clear();
        ll a = visit(s);
        if (a > 0) {
            for (ll i = 1; i < (ll) path.size(); i++) {
                flows[path[i - 1]][path[i]] += a;
                flows[path[i]][path[i - 1]] -= a;
            }
            o += a;
        } else {
            break;
        }
    }
    cout << o << endl;
    return 0;
}

#include <bits/stdc++.h>

using namespace std;

struct Dinic {
    //using F = int; const static F INF = 0x3f3f3f3f;
    using F = long long; const static F INF = 0x3f3f3f3f3f3f3f3f;
    struct Edge {
        int v, bro; F cap;
        Edge() {}
        Edge(int _v, int _bro, F _cap) : v(_v), bro(_bro), cap(_cap) {}
    };
    vector<Edge> e;
    vector<int> pos, cur;
    int n, s, t, m;
    Dinic(int _n, int _s, int _t) : n(_n), s(_s), t(_t), m(0) {
        pos.assign(n, -1);
        cur.resize(n);
        d.resize(n);
        e.reserve(4e5);
    }
    void add(int u, int v, F c=INF) {
        assert(u < n && v < n);
        e.emplace_back(v, pos[u], c); pos[u] = m++;
        e.emplace_back(u, pos[v], 0); pos[v] = m++;
    }
    vector<int> d;
    // build layer graph
    bool bfs() {
        fill(d.begin(), d.end(), -1);
        d[s] = 0;
        queue<int> q; q.push(s);
        while (!q.empty()) {
            int u = q.front(); q.pop();
            for (int i = cur[u] = pos[u]; i != -1; i = e[i].bro) {
                int v = e[i].v;
                if (d[v] == -1 && e[i].cap != 0) {
                    d[v] = d[u] + 1;
                    q.push(v);
                }
            }
        }
        return d[t] != -1;
    }
    // find blocking flow
    F dfs(int u, F lim) {
        if (u == t) return lim;
        F tot = 0;
        for (int& i = cur[u]; i != -1; i = e[i].bro) {
            int v = e[i].v;
            if (e[i].cap != 0 && d[v] == d[u] + 1) {
                F flow = dfs(v, min(e[i].cap, lim-tot));
                tot += flow;
                e[i].cap -= flow;
                e[i^1].cap += flow;
                if (tot == lim) return lim;
            }
        }
        return tot;
    }
    F flow() {
        F res = 0;
        while (bfs()) {
            res += dfs(s, INF);
        }
        return res;
    }
};

struct ProjectSelection {
    int n;
    int s,t;
    Dinic mc;
    using F = Dinic::F;
    ProjectSelection(int _n) : n(_n)
        , s(n)
        , t(n+1)
        , mc(n+2, s, t)
    {}

    void add_proj(int i, F profit) {
        if (profit >= 0) {
            mc.add(s, i, profit);
        } else {
            mc.add(i, t, -profit);
        }
    }

    // !!Caution: proj without dep-relation not included in flow
    // u,v: [0..n)
    void add_dep(int u, int v) {
        mc.add(u, v);
    }

    F profit() {
        return mc.flow();
    }
};

template <typename T=int>
struct Compress {
    map<T, int> id;
    vector<T> num;

    inline int get_id(T x) {
        if (!id.count(x)) {
            id[x] = num.size();
            num.emplace_back(x);
        }
        return id[x];
    }
    inline int get_num(int i) {
        assert(0 <= i && i < num.size());
        return num[i];
    }
};

struct ProjectSelectionDumper {
    using F = Dinic::F;
    F sum;
    ProjectSelectionDumper(const vector<F>& profits, const vector<pair<int, int>>& deps) {
        vector<bool> trk(profits.size(), false);
        Compress<int> c;
        for (auto& p: deps) {
            c.get_id(p.first);
            c.get_id(p.second);
            trk[p.first] = true;
            trk[p.second] = true;
        }

        ProjectSelection ps(c.num.size());
        sum = 0;
        for (int i = 0; i < (int)profits.size(); i++) {
            if (trk[i]) {
                ps.add_proj(c.get_id(i), profits[i]);
            } else if (profits[i] > 0) {
                sum += profits[i];
            }
        }
        for (auto& p: deps) {
            int u = c.get_id(p.first);
            int v = c.get_id(p.second);
            ps.add_dep(u, v);
        }
        sum += ps.profit();
    }
};

using ll=long long;
const int INF = 0x3f3f3f3f;
const int N = 111;
int d[N][N];

void solve() {
    int n,m;
    cin >> n >> m;
    memset(d, INF, sizeof d);
    for (int _ = 0; _ < m; _++) {
        int x,y;
        cin >> x >> y;
        x--;y--;
        d[x][y] = d[y][x] = 1;
    }
    for (int i = 0; i < n; i++) {
        d[i][i] = 0;
    }
    for (int k = 0; k < n; k++) {
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                if (d[i][k] < INF && d[k][j] < INF) {// for negative
                    d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
                }
            }
        }
    }

    int s,b,k;
    cin >> s >> b >> k;
    vector<int> x(s), a(s), f(s);
    vector<ll> p(s);
    for (int i = 0; i < s; i++) {
        cin >> x[i] >> a[i] >> f[i] >> p[i];
        --x[i];
    }
    vector<map<int,int>> dg(n);
    for (int _ = 0; _ < b; _++) {
        int i,d,g;
        cin >> i >> d >> g;
        i--;
        dg[i][d] = max(dg[i][d], g);
    }
    for (int i = 0; i < n; i++) {
        int pre = 0;
        for (auto it = dg[i].begin(); it != dg[i].end(); it++) {
            it->second = pre = max(it->second, pre);
        }
    }

    for (int i = 0; i < s; i++) {
        int mx = -1;
        int u = x[i];
        for (int j = 0; j < n; j++) {
            if (!dg[j].empty() && f[i] >= d[u][j]) {
                auto it = dg[j].upper_bound(a[i]);
                if (it != dg[j].begin()) {
                    --it;
                    mx = max(mx, it->second);
                }
            }
        }
        if (mx < 0) p[i] = -(1ll<<62);
        else p[i] = mx - p[i];
    }

    vector<pair<int, int>> deps;
    for (int _ = 0; _ < k; _++) {
        int u,v;
        cin >> u >> v;
        u--;v--;
        deps.emplace_back(u, v);
    }

    ProjectSelectionDumper ps(p, deps);

    cout << ps.sum << "\n";
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    solve();
    cout << endl;
}

#include <bits/stdc++.h>
#define db(x) cout << (x) << '\n';
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
#define MAXN 105
#define oo2 (1e9+7)
#define MAXM 100005

int d[MAXN][MAXN];
vector<pii> bs[MAXN];
int mbs[MAXN][MAXM],pl[MAXM],pp[MAXM][4];

template<typename flow_type>
struct dinic
{
	struct edge
	{
		size_t src, dst, rev;
		flow_type flow, cap;
	};

	int n;
	vector<vector<edge>> adj;

	dinic(int n) : n(n), adj(n), level(n), q(n), it(n) {}

	void add_edge(size_t src, size_t dst, flow_type cap, flow_type rcap = 0)
	{
		adj[src].push_back({src, dst, adj[dst].size(), 0, cap});
		if (src == dst) adj[src].back().rev++;
		adj[dst].push_back({dst, src, adj[src].size() - 1, 0, rcap});
	}

	vector<int> level, q, it;

	bool bfs(int source, int sink)
	{
		fill(level.begin(), level.end(), -1);
		for (int qf = level[q[0] = sink] = 0, qb = 1; qf < qb; ++qf)
		{
			sink = q[qf];
			for (edge &e : adj[sink])
			{
				edge &r = adj[e.dst][e.rev];
				if (r.flow < r.cap && level[e.dst] == -1)
					level[q[qb++] = e.dst] = 1 + level[sink];
			}
		}
		return level[source] != -1;
	}

	flow_type augment(int source, int sink, flow_type flow)
	{
		if (source == sink) return flow;
		for (; it[source] != adj[source].size(); ++it[source])
		{
			edge &e = adj[source][it[source]];
			if (e.flow < e.cap && level[e.dst] + 1 == level[source])
			{
				flow_type delta = augment(e.dst, sink,
								  min(flow, e.cap - e.flow));
				if (delta > 0)
				{
					e.flow += delta;
					adj[e.dst][e.rev].flow -= delta;
					return delta;
				}
			}
		}
		return 0;
	}

	flow_type max_flow(int source, int sink)
	{
		for (int u = 0; u < n; ++u)
			for (edge &e : adj[u]) e.flow = 0;
		flow_type flow = 0;
		flow_type oo = numeric_limits<flow_type>::max();

		while (bfs(source, sink))
		{
			fill(it.begin(), it.end(), 0);
			for (flow_type f; (f = augment(source, sink, oo)) > 0;)
				flow += f;

		} // level[u] = -1 => source side of min cut
		return flow;
	}
};

int main()
{
    ios_base::sync_with_stdio(0);
    cin.tie(0);

    int n,m,u,v;
    cin >> n >> m;
    for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
            d[i][j]=oo2;
    for(int i=0;i<m;i++)
    {
        cin >> u >> v;
        u--,v--;
        d[u][v]=d[v][u]=1;
    }

    for(int i=0;i<n;i++)
        d[i][i]=0;
    for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
            for(int k=0;k<n;k++)
                d[j][k]=min(d[j][k],d[j][i]+d[i][k]);

    int s,b,k,gg,de;
    cin >> s >> b >> k;
    for(int i=0;i<s;i++)
    {
        cin >> pp[i][0] >> pp[i][1] >> pp[i][2] >> pp[i][3];
        pp[i][0]--;
    }
    for(int i=0;i<b;i++)
    {
        cin >> u >> de >> gg;
        u--;
        bs[u].push_back(pii(de,gg));
    }

    for(int i=0;i<n;i++)
    {
        sort(bs[i].begin(),bs[i].end());
        int ma=0;
        for(int j=0;j<bs[i].size();j++)
        {
            ma=max(ma,bs[i][j].second);
            mbs[i][j]=ma;
        }
    }

    dinic<ll> g(2+s);
    ll s1=0;
    for(int i=0;i<s;i++)
    {
        int ma=0;
        for(int j=0;j<n;j++)
        {
            if(d[j][pp[i][0]]>pp[i][2])
                continue;
            int pos=lower_bound(bs[j].begin(),bs[j].end(),pii(pp[i][1],oo2))-bs[j].begin();
            if(pos)
                ma=max(ma,mbs[j][pos-1]);
        }
        pl[i]=ma-pp[i][3];
        if(pl[i]>0)
        {
            g.add_edge(0,i+1,pl[i]);
            s1+=pl[i];
        }
        if(pl[i]<0)
            g.add_edge(i+1,s+1,-pl[i]);
    }

    for(int i=0;i<k;i++)
    {
        cin >> u >> v;
        g.add_edge(u,v,oo2*oo2);
    }

    db(s1-g.max_flow(0,s+1))

    return 0;
}

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef ll F;
const int N    = 1e2 + 10;
const int maxs = 1e5 + 10;
const int maxn = 2e3 + 10;
const int maxm = 6e3 + 10;
const ll INF  = 2e13;
const F  INF_CAP = INF;

struct spaceship{
    int x,a,f,p;
}sp[maxs];
struct base {
    int d,g;
    bool operator < (const base& b)const {
        return d < b.d;
    }
};

ll best_goal[maxs];

vector<base> ba[N];
vector<int>  pre[N];
vector<int>  g[maxs];
bool used[maxs];
int w[N][N],id[maxs];

struct Dinic{
    int n,m,s,t,pos;
    int d[maxn],head[maxn],que[maxn],ptr[maxn];
    int to[maxm],nxt[maxm];
    F  cap[maxm];
    void init() {
        memset(head,-1,sizeof head);
    }
    void addedge(int a,int b,F c) {
//        printf("%d %d %lld\n",a,b,c);
//        printf("%d\n",m);
        cap[m] = c;to[m] = b;nxt[m] = head[a];head[a] = m++;
        cap[m] = 0;to[m] = a;nxt[m] = head[b];head[b] = m++;
    }
    bool bfs() {
        pos = 0;
        memset(d,-1,sizeof d);
        que[pos++] = s;
        d[s] = 0;
        for(int i = 0;i < pos;i++) {
            int x = que[i];
            for(int u = head[x];~u;u = nxt[u]) {
                if(d[to[u]] == -1&&cap[u]) {
                    d[to[u]] = d[x] + 1;
                    que[pos++] = to[u];
                }
            }
        }
        return d[t] != -1;
    }
    F dfs(int o,F mi) {
        if(o == t||mi == 0) return mi;
        F res = 0;
        for(int &x = ptr[o];~x;x = nxt[x]) if(d[to[x]] == d[o] + 1&&cap[x]){
            F tmp = dfs(to[x],min(mi,cap[x]));
            cap[x] -= tmp;
            cap[x^1] += tmp;
            mi -= tmp;
            res += tmp;
            if(mi == 0) return 0;
        }
        return res;
    }
    F maxflow(int s,int t) {
        this->s = s;this->t = t;
        F res = 0;
        while(bfs()) {
            memcpy(ptr,head,sizeof head);
            res += dfs(s,INF_CAP);
        }
        return res;
    }
}D;

int main() {
    D.init();
    int n,m,s,b,k;
    scanf("%d%d",&n,&m);
    for(int i = 1;i <= n;i++) fill(w[i] + 1,w[i] + 1 + n,n),w[i][i] = 0;
    for(int i = 0;i < m;i++) {
        int a,b;
        scanf("%d%d",&a,&b);
        w[b][a] = w[a][b] = min(w[a][b],1);
    }
    for(int d = 1;d <= n;d++) {
        for(int i = 1;i <= n;i++) {
            for(int j = 1;j <= n;j++) {
                w[i][j] = min(w[i][j],w[i][d] + w[d][j]);
            }
        }
    }
    scanf("%d%d%d",&s,&b,&k);
    for(int i = 1;i <= s;i++) {
        scanf("%d%d%d%d",&sp[i].x,&sp[i].a,&sp[i].f,&sp[i].p);
    }
    for(int i = 0;i < b;i++) {
        int x,d,g;
        scanf("%d%d%d",&x,&d,&g);
        ba[x].push_back(base{d,g});
    }
    for(int i = 1;i <= n;i++) if(ba[i].size()){
        int sz = (int)ba[i].size();
        sort(ba[i].begin(),ba[i].end());
        pre[i].resize(sz);
        pre[i][0] = ba[i][0].g;
        for(int j = 1;j < sz;j++) pre[i][j] = max(pre[i][j-1],ba[i][j].g);
    }
    for(int i = 1;i <= s;i++) {
        best_goal[i] = -INF_CAP;
        int x = sp[i].x;
        for(int j = 1;j <= n;j++) {
            if(w[x][j] <= sp[i].f) {
                int pos = upper_bound(ba[j].begin(),ba[j].end(),base{sp[i].a,0}) - ba[j].begin();
                --pos;
                if(pos >= 0) {
                    best_goal[i] = max(best_goal[i],(ll)pre[j][pos] - sp[i].p);
                }
            }
        }
    }
    for(int i = 0;i < k;i++) {
        int a,b;
        scanf("%d%d",&a,&b);
        g[a].push_back(b);
        used[a] = used[b] = 1;
    }
    ll ans = 0;
    int cnt = 0;
    for(int i = 1;i <= s;i++) {
        if(!used[i]) {
            if(best_goal[i] > 0) ans += best_goal[i];
        }
        else {
            id[i] = ++cnt;
        }
    }

    int st = 0,ed = cnt + 1;
    cnt = 0;
    for(int i = 1;i <= s;i++) {
        if(used[i]) {
            if(best_goal[i] >= 0) ans += best_goal[i],D.addedge(st,id[i],best_goal[i]);
            else D.addedge(id[i],ed,-best_goal[i]);
            for(auto& u:g[i]) D.addedge(id[i],id[u],INF_CAP);
        }
    }
    // printf("%lld\n",ans);
    ans -= D.maxflow(st,ed);
    printf("%lld\n",ans);
    return 0;
}

#include <iostream>
#include <fstream>
#include <numeric>
#include <iomanip>
#include <cstring>
#include <string>
#include <algorithm>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <deque>

#define sz(a) (int)((a).size())
#define all(a) (a).begin(), (a).end()
#define pb push_back

using namespace std; using ll = long long; using vi = vector<int>; using pii = pair<int, int>; using ld = long double;

const int inf = (int)1e9 + 100;

int n, m;
int d[100][100];
int s, b, k;

struct ship {
	int x, a, f, p;
} ss[100000];

struct base {
	int x, d, g;
} bb[100000];

struct maxflow {
	struct edge {
		int to, c, f;
	};

	vector<edge> e;
	vector<vi> g;
	int N, S, T;
	vi pt, d;
	int A;

	bool bfs() {
		fill_n(d.begin(), N, inf);
		d[S] = 0;
		queue<int> q;
		q.push(S);
		while (!q.empty()) {
			int v = q.front();
			q.pop();
			for (int i : g[v]) {
				edge& ee = e[i];
				if (ee.c - ee.f >= A && d[ee.to] == inf) {
					d[ee.to] = d[v] + 1;
					q.push(ee.to);
				}
			}

		}
		return (d[T] != inf);
	}

	int dfs(int v, int cmin) {
		if (v == T) {
			return cmin;
		}
		for (; pt[v] < sz(g[v]); pt[v]++) {
			int i = g[v][pt[v]];
			edge& ee = e[i];
			if (ee.c - ee.f >= A && d[ee.to] == d[v] + 1) {
				int f = dfs(ee.to, min(cmin, ee.c - ee.f));
				if (f > 0) {
					ee.f += f;
					e[i ^ 1].f -= f;
					return f;
				}
			}
		}
		return 0;
	}

	void dinic() {
		d.resize(N);
		pt.resize(N);
		int mf = 0;
		for (A = inf; A; A >>= 1) {
			while (bfs()) {
				fill_n(pt.begin(), N, 0);
				while (dfs(S, inf));
			}
		}
	}

	void addEdge(int u, int v, int c) {
		static int i = 0;
		e.pb({ v, c, 0 });
		e.pb({ u, 0, 0 });
		g[u].pb(i);
		g[v].pb(i ^ 1);
		i += 2;
	}

	void zhfs(int v, vector<bool>& was) {
		was[v] = true;
		for (int i : g[v]) {
			edge& ee = e[i];
			if (ee.c - ee.f > 0 && !was[ee.to]) {
				zhfs(ee.to, was);
			}
		}
	}
};

vi g1[100000];
vector<pii> e;
bool ban[100000];
int w[100000];

void dfs(int v) {
	ban[v] = true;
	for (int to : g1[v]) if(!ban[to]) dfs(to);
}

vector<pii> pl[100];
vi pm[100];

int32_t main() {
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	//ifstream cin("in.txt");
	cin >> n >> m;
	for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) if(i != j) d[i][j] = inf;
	for (int i = 0; i < m; i++) {
		int u, v; cin >> u >> v; --u; --v; d[u][v] = d[v][u] = 1;
	}
	for (int k = 0; k < n; k++) for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
	cin >> s >> b >> k;
	for (int i = 0; i < s; i++) cin >> ss[i].x >> ss[i].a >> ss[i].f >> ss[i].p, --ss[i].x;
	for (int i = 0; i < b; i++) cin >> bb[i].x >> bb[i].d >> bb[i].g, --bb[i].x, pl[bb[i].x].pb({ bb[i].d, bb[i].g });
	for (int i = 0; i < n; i++) {
		if (pl[i].empty()) continue;
		sort(all(pl[i]));
		pm[i].resize(sz(pl[i]));
		pm[i][0] = pl[i][0].second;
		for (int j = 1; j < sz(pm[i]); j++) {
			pm[i][j] = max(pm[i][j - 1], pl[i][j].second);
		}
	}
	vi broken;
	maxflow grape;
	grape.N = s + 2;
	grape.S = grape.N - 2;
	grape.T = grape.N - 1;
	grape.g.resize(grape.N);
	vi ord(s); iota(all(ord), 0);
	sort(all(ord), [](int i, int j) { return ss[i].a < ss[j].a; });
	vi pt(n, -1);
	for (int i : ord) {
		int hi = -1;
		//for (int p = 0; p < n; p++) if (ss[i].f >= d[ss[i].x][p]) for (pii bas : pl[p]) if (ss[i].a >= bas.first) hi = max(hi, bas.second);
		// me for (int p = 0; p < n; p++) if (ss[i].f >= d[ss[i].x][p]) for (int t = 0; t < sz(pl[p]) && ss[i].a >= pl[p][t].first; t++) hi = max(hi, pm[p][t]);
 		//for (int j = 0; j < b; j++) if (ss[i].a >= bb[j].d && ss[i].f >= d[ss[i].x][bb[j].x]) hi = max(hi, bb[j].g);
		for (int p = 0; p < n; p++) if(ss[i].f >= d[ss[i].x][p]) {
			while (pt[p] + 1 < sz(pl[p]) && ss[i].a >= pl[p][pt[p] + 1].first) pt[p]++;
			if (pt[p] != -1) hi = max(hi, pm[p][pt[p]]);
		}
		if (hi == -1) broken.pb(i);
		else {
			hi -= ss[i].p;
			if (hi < 0) grape.addEdge(i, grape.T, -hi);
			else if (hi > 0) grape.addEdge(grape.S, i, hi);
			w[i] = hi;
			//cout << i << ' ' << w[i] << endl;
		}
	}
	for (int i = 0; i < k; i++) {
		int u, v; cin >> u >> v; --u; --v;
		g1[v].pb(u); e.pb({ u, v });
	}
	for (int u : broken) if (!ban[u]) dfs(u);
	for (pii r : e) {
		int u = r.first, v = r.second;
		if (!ban[u] && !ban[v]) grape.addEdge(u, v, inf);
	}
	grape.dinic();
	vector<bool> was(grape.N, false);
	grape.zhfs(grape.S, was);
	ll ans = 0;
	for (int u = 0; u < s; u++) {
		if (was[u]) {
			ans += w[u];
		}
	}
	cout << ans;
}

#include <bits/stdc++.h>

#define fast_cin() ios_base::sync_with_stdio(false); cin.tie(0);
#define pb push_back

using namespace std;

typedef long double ld;
typedef long long ll;
typedef long long LL;
typedef pair <int, int> pii;
typedef pair <ll, ll> pll;

struct Edge {
  int u, v;
  LL cap, flow;
  Edge() {}
  Edge(int u, int v, LL cap): u(u), v(v), cap(cap), flow(0) {}
};

struct Dinic {
  int N;
  vector<Edge> E;
  vector<vector<int>> g;
  vector<int> d, pt;

  Dinic(int N): N(N), E(0), g(N), d(N), pt(N) {}

  void AddEdge(int u, int v, LL cap) {
    if (u != v) {
      E.emplace_back(Edge(u, v, cap));
      g[u].emplace_back(E.size() - 1);
      E.emplace_back(Edge(v, u, 0));
      g[v].emplace_back(E.size() - 1);
    }
  }

  bool BFS(int S, int T) {
    queue<int> q({S});
    fill(d.begin(), d.end(), N + 1);
    d[S] = 0;
    while(!q.empty()) {
      int u = q.front(); q.pop();
      if (u == T) break;
      for (int k: g[u]) {
        Edge &e = E[k];
        if (e.flow < e.cap && d[e.v] > d[e.u] + 1) {
          d[e.v] = d[e.u] + 1;
          q.emplace(e.v);
        }
      }
    }
    return d[T] != N + 1;
  }

  LL DFS(int u, int T, LL flow = -1) {
    if (u == T || flow == 0) return flow;
    for (int &i = pt[u]; i < g[u].size(); ++i) {
      Edge &e = E[g[u][i]];
      Edge &oe = E[g[u][i]^1];
      if (d[e.v] == d[e.u] + 1) {
        LL amt = e.cap - e.flow;
        if (flow != -1 && amt > flow) amt = flow;
        if (LL pushed = DFS(e.v, T, amt)) {
          e.flow += pushed;
          oe.flow -= pushed;
          return pushed;
        }
      }
    }
    return 0;
  }

  LL MaxFlow(int S, int T) {
    LL total = 0;
    while (BFS(S, T)) {
      fill(pt.begin(), pt.end(), 0);
      while (LL flow = DFS(S, T))
        total += flow;
    }
    return total;
  }
};

struct ship_t {
	ll x, a, f, p;
};

struct base_t {
	ll x, d, g;
	bool operator<(const base_t &o) const {
		return d < o.d;
	}
};

const int N = 1e2 + 10, S = 1e5 + 10;
const ll inf = 1e12 + 42;

ship_t ship[S];
base_t base[S];
ll g[N][N];
vector<int> dep[S];
vector<pll> bases_at[N];
bool seen[S];
ll val[S];

int main()
{
	fast_cin();
	int n, m;
	cin >> n >> m;
	for (int i = 1; i <= n; ++i) {
		for (int j = i + 1; j <= n; ++j) {
			g[i][j] = g[j][i] = inf;
		}
	}
	for (int i = 0; i < m; ++i) {
		int u, v;
		cin >> u >> v;
		g[u][v] = g[v][u] = min(g[u][v], 1ll);
	}
	for (int k = 1; k <= n; ++k) {
		for (int i = 1; i <= n; ++i) {
			for (int j = 1; j <= n; ++j) {
				g[i][j] = min(g[i][j], g[i][k] + g[k][j]);
			}
		}
	}
	int s, b, k;
	cin >> s >> b >> k;
	for (int i = 1; i <= s; ++i) {
		cin >> ship[i].x >> ship[i].a >> ship[i].f >> ship[i].p;
	}
	for (int i = 1; i <= b; ++i) {
		cin >> base[i].x >> base[i].d >> base[i].g;
	}
	sort(base + 1, base + 1 + b);
	for (int i = 1; i <= b; ++i) {
		int p = base[i].x;
		if (bases_at[p].empty() or bases_at[p].back().second < base[i].g) {
			bases_at[p].pb({base[i].d, base[i].g});
		}
	}
	Dinic dinic(s + 2);
	int source = 0, sink = s + 1;
	ll ans = 0;
	for (int i = 1; i <= s; ++i) {
		for (int p = 1; p <= n; ++p) {
			if (g[ship[i].x][p] > ship[i].f) {
				continue;
			}
			auto it = upper_bound(bases_at[p].begin(), bases_at[p].end(), make_pair(ship[i].a, inf));
			if (it != bases_at[p].begin()) {
				--it;
				val[i] = max(val[i], it->second);
			}
		}
		val[i] -= ship[i].p;
		if (val[i] >= 0) {
			ans += val[i];
			dinic.AddEdge(source, i, val[i]);
		} else {
			dinic.AddEdge(i, sink, -val[i]);
		}
	}
	for (int i = 1; i <= k; ++i) {
		int u, v;
		cin >> u >> v;
		dep[u].pb(v);
	}
	for (int i = 1; i <= s; ++i) {
		if (val[i] < 0) {
			continue;
		}
		vector<int> vis = {i};
		queue<int> q;
		q.push(i);
		seen[i] = true;
		while (!q.empty()) {
			int u = q.front();
			q.pop();
			if (val[u] < 0) {
				dinic.AddEdge(i, u, inf);
			}
			for (auto &v : dep[u]) {
				if (!seen[v]) {
					seen[v] = true;
					vis.pb(v);
					q.push(v);
				}
			}
		}
		for (auto &u : vis) {
			seen[u] = false;
		}
	}
	cout << ans - dinic.MaxFlow(source, sink);
}

#include <bits/stdc++.h>
//
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 100015;
const int maxm = 1000005;
int g[105][105];
int num[maxn];
int cnt;
void floyed(int n){
    for(int k = 1; k <= n; k++){
        for(int i = 1; i <= n; i++){
            for(int j = 1; j <= n; j++){
                g[i][j] = min(g[i][j], g[i][k]+g[k][j]);
            }
        }
    }
};
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
    while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
struct Edge{
    int to,next,cap,flow;
}edge[maxm];
int tol,head[maxn];
void init()
{
    tol=2;
    memset(head,-1,sizeof(head));
}
void addedge(int u,int v,int w,int rw=0)
{
    edge[tol].to=v;edge[tol].cap=w;edge[tol].flow=0;
    edge[tol].next=head[u];head[u]=tol++;
    edge[tol].to=u;edge[tol].cap=rw;edge[tol].flow=0;
    edge[tol].next=head[v];head[v]=tol++;
}
int Q[maxn];
int dep[maxn],cur[maxn],sta[maxn];
bool bfs(int s,int t,int n)
{
    int front=0,tail=0;
    memset(dep,-1,sizeof(dep[0])*(n+1));
    dep[s]=0;
    Q[tail++]=s;
    while(front<tail){
        int u=Q[front++];
        for(int i=head[u];i!=-1;i=edge[i].next){
            int v=edge[i].to;
            if(edge[i].cap>edge[i].flow&&dep[v]==-1){
                dep[v]=dep[u]+1;
                if(v==t){
                    return true;
                }
                Q[tail++]=v;
            }
        }
    }
    return false;
}
long long dinic(int s,int t,int n)
{
    long long maxflow=0;
    while(bfs(s,t,n)){
        for(int i=0;i<n;i++){
            cur[i]=head[i];
        }
        int u=s,tail=0;
        while(cur[s]!=-1){
            if(u==t){
                int tp=INF;
                for(int i=tail-1;i>=0;i--){
                    tp=min(tp,edge[sta[i]].cap-edge[sta[i]].flow);
                }
                maxflow+=tp;
                for(int i=tail-1;i>=0;i--){
                    edge[sta[i]].flow+=tp;
                    edge[sta[i]^1].flow-=tp;
                    if(edge[sta[i]].cap-edge[sta[i]].flow==0){
                        tail=i;
                    }
                }
                u=edge[sta[tail]^1].to;
            }else if(cur[u]!=-1&&edge[cur[u]].cap>edge[cur[u]].flow&&dep[u]+1==dep[edge[cur[u]].to]){
                sta[tail++]=cur[u];
                u=edge[cur[u]].to;
            }else{
                while(u!=s&&cur[u]==-1){
                    u=edge[sta[--tail]^1].to;
                }
                cur[u]=edge[cur[u]].next;
            }
        }
    }
    return maxflow;
}
//vector<int>fuck[100005];
int fuckacm[100005];
int ps[105];
int in[maxn], out[maxn], shipos[maxn], atk[maxn], f[maxn], p[maxn], baspos[maxn], d[maxn], gold[maxn], val[maxn];
bool svis[maxn];
#define pii pair<int,int>
vector<pii> v1[105];
int main(){
    int n, m, u, v, s, b, k;
    n = read(), m = read();
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n; j++){
            if(i==j) g[i][j] = 0;
            else g[i][j] = g[j][i] = INF;
        }
    }
    for(int i = 1; i <= m; i++){
        u = read(), v = read();
        g[u][v] = g[v][u] = 1;
    }
    floyed(n);
    s = read(), b = read(), k = read();
    for(int i = 1; i <= s; i++){
        shipos[i] = read(), atk[i] = read(), f[i] = read(), p[i] = read();
    }
    for(int i = 1; i <= b; i++){
        baspos[i] = read(), d[i] = read(), gold[i] = read();
        v1[baspos[i]].emplace_back(pii(d[i], gold[i]));
    }
    for(int i = 1; i <= k; i++){
        int tmp1, tmp2;
        tmp1 = read(), tmp2 = read();
        fuckacm[tmp1] = tmp2;
        in[tmp2]++, out[tmp1]++;
    }
    for(int i = 1; i <= n; i++){
        sort(v1[i].begin(), v1[i].end()); ps[i] = 0;
        for(int j = 1; j < v1[i].size(); j++){
            v1[i][j].second = max(v1[i][j].second, v1[i][j-1].second);
        }
    }
    for(int i = 1; i <= s; i++){
        int ma = 0;
        for(int j = 1; j <= n; j++){
            if(g[shipos[i]][j] <= f[i]){
                if(v1[j].empty()) continue;
                while(ps[j] < v1[j].size()-1 && v1[j][ps[j]+1].first <= atk[i]) ps[j]++;
                if(v1[j][ps[j]].first <= atk[i]) ma = max(ma, v1[j][ps[j]].second);
            }
        }
        val[i] = ma-p[i];
    }
    long long ans = 0;
    for(int i = 1; i <= s; i++){
        if(in[i] == 0 && out[i] > 0 && !svis[i]){
            if(val[i] <= 0){
                svis[i] = true;
            }
        }
        if(in[i] == 0 && out[i] == 0 && val[i]>0 && !svis[i]){
            ans += val[i];
            svis[i] = true;
        }
        if(in[i] == 0 && out[i] == 0 && val[i] < 0 && !svis[i]){
            svis[i] = true;
        }
    }
    int S = 2015+1, T = S+1;
    init();
    for(int i = 1; i <= s; i++){
        if(!svis[i]){
            if(val[i] > 0){
                num[i] = ++cnt;
                addedge(S, cnt, val[i]);
                ans += val[i];
            }
            else{
                num[i] = ++cnt;
                addedge(cnt, T, -val[i]);
            }
        }
    }
    for(int i = 1; i <= s; i++){
        if(!svis[i] && val[i] > 0)
            addedge(num[i], num[fuckacm[i]], INF);
    }
    ans -= dinic(S, T, T+1);
    cout << ans;
    return 0;
}

//#pragma GCC optimize ("Ofast")
//#pragma GCC target ("avx,avx2,fma")

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;

typedef pair<int,int> pii;
typedef pair<ll,ll> pll;

#define F first
#define S second
#define pb push_back
#define eb emplace_back
#define mk make_pair
#define all(x) x.begin(), x.end()

#define REP(i,n) for(int i = 0; i < int(n); i++)
#define FOR(i,a,b) for(int i = a; i <= int(b); i++)

const int N = 105;
const int INF = 1e9+5;
const ll INF_LL = 1e15+5;

int g[N][N], dist[N][N];

struct Ship {
	int loc, attack, fuel, price;

	void read() {
		cin >> loc >> attack >> fuel >> price;
		--loc;
	}
};

vector<pii> reward[N];

struct Base {
	int loc, defence, gold;

	void read() {
		cin >> loc >> defence >> gold;
		--loc;
		reward[loc].emplace_back(defence, gold);
	}

};

template<typename T>
void max_self(T& a, T b) {
	a = max(a, b);
}

// Dinic's algoritm for maximum flow O(E*V^2)
// tested on: https://www.spoj.com/problems/FASTFLOW/

template<typename flow_t>
class Dinic {
public:

    Dinic(int _n, int _source, int _sink) : n(_n), source(_source), sink(_sink) {
        g.resize(n);
        flow.resize(n, vector<flow_t>(n));
        level.resize(n);
        ptr.resize(n);
    }

    void add_edge(int from, int to, flow_t cap) {
        g[from].push_back(to);
        g[to].push_back(from);
        flow[from][to] += cap;
    }

    bool bfs() {
        vector<int> q{source};
        for(int i = 0; i < (int) q.size(); i++) {
            int u = q[i];
            for(int v : g[u]) {
                if(level[v] == -1 && flow[u][v] > 0) {
                    level[v] = level[u] + 1;
                    q.push_back(v);
                }
            }
        }

        return level[sink] != -1;
    }

    flow_t dfs(int u, flow_t pushed) {
        if(pushed == 0) {
            return 0;
        }
        if(u == sink) {
            return pushed;
        }
        for(int& pos = ptr[u]; pos < (int) g[u].size(); pos++) {
            int v = g[u][pos];
            if(level[v] != level[u] + 1 || flow[u][v] == 0) {
                continue;
            }
            flow_t maybe_push = dfs(v, min(pushed, flow[u][v]));
            if(maybe_push == 0) {
                continue;
            }
            flow[u][v] -= maybe_push;
            flow[v][u] += maybe_push;
            return maybe_push;
        }
        return 0;
    }

    flow_t max_flow() {
        flow_t mf(0);
        while(true) {
            level.assign(n, -1);
            level[source] = 0;
            if(!bfs()) {
                break;
            }
            ptr.assign(n, 0);
            flow_t now;
            do {
                now = dfs(source, FLOW_MAX);
                mf += now;
            } while(now != 0);
        }

        return mf;
    }
private:
    const flow_t FLOW_MAX = numeric_limits<flow_t>::max() / 2;
    vector<vector<int>> g;
    vector<vector<flow_t>> flow;
    vector<int> level, ptr;
    int n, source, sink;
};

int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);

	fill((int *) dist, (int *) dist + N * N, INF);
	REP(i, N) dist[i][i] = 0;

	int n, m;
	cin >> n >> m;

	REP(i, m) {
		int a, b;
		cin >> a >> b;
		--a, --b;
		g[a][b] = g[b][a] = 1;
		dist[a][b] = dist[b][a] = 1;
	}

	REP(k, n)REP(i, n)REP(j, n) {
		dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
	}

	int S, B, K;
	cin >> S >> B >> K;
	vector<Ship> ships(S);
	vector<Base> bases(B);

	for(auto& s : ships) {
		s.read();
	}
	for(auto& b : bases) {
		b.read();
	}

	REP(i, n) {
		sort(all(reward[i]));
		int sz = reward[i].size();
		FOR(j, 1, sz-1) {
			reward[i][j].S = max(reward[i][j].S, reward[i][j-1].S);
		}
	}
	//for each ship, find the best base to attack

	vector<long long> ship_reward(S, -INF_LL);
	REP(i, S) {
		Ship s = ships[i];
		REP(base, n) {
			int lo = 0, hi = (int) reward[base].size()-1;
			int idx = -1;
			while(lo <= hi) {
				int mid = (lo + hi)/2;
				if(reward[base][mid].F <= s.attack) {
					idx = mid;
					lo = mid+1;
				}
				else {
					hi = mid-1;
				}
			}
			if(idx == -1) {
				continue;
			}
			max_self(ship_reward[i], (long long) reward[base][idx].S - s.price);
		}
	}
	//#warning TODO: read dependencies

	vector<pii> dependencies;
	vector<int> have_dep(S);
	REP(i, K) {
		int a, b;
		cin >> a >> b;
		--a, --b;
		have_dep[a] = 1;
		dependencies.emplace_back(a, b);
	}
	long long ans = 0;
	REP(i, S) {
		if(ship_reward[i] > 0) {
			ans += ship_reward[i];
		}
	}
	map<int,int> id;
	int nodes = 0;
	for(auto [u, v] : dependencies) {
		if(!id.count(u)) {
			id[u] = nodes++;
		}
		if(!id.count(v)) {
			id[v] = nodes++;
		}
	}
	int source = nodes++;
	int sink = nodes++;

	Dinic<long long> graph(nodes, source, sink);

	for(auto [u, _] : id) {
		if(ship_reward[u] >= 0) {
			graph.add_edge(source, id[u], ship_reward[u]);
		}
		else {
			graph.add_edge(id[u], sink, -ship_reward[u]);
		}
	}
	for(auto [u, v] : dependencies) {
		graph.add_edge(id[u], id[v], INF_LL);
	}

	ans -= graph.max_flow();
	cout << ans << "\n";

}

#include <bits/stdc++.h>
using namespace std;

// Template Headers {{{
using pii = pair<int, int>; using vpii = vector<pii>;
using vi = vector<int>; using vvi = vector<vi>;
using ll = long long; using vll = vector<long long>;
template <class T> using min_queue = priority_queue<T, vector<T>, greater<T>>;
template <class T> istream &operator>>(istream &, vector<T> &);
template <class T> ostream &operator<<(ostream &, const vector<T> &);
template <class T, class U> istream &operator>>(istream &, pair<T, U> &);
template <class T, class U> ostream &operator<<(ostream &, const pair<T, U> &);
template<class T> struct Inf { static constexpr T inf() { return std::numeric_limits<T>::has_infinity() ? std::numeric_limits<T>::infinty() : std::numeric_limits<T>::max(); } };
template<> struct Inf<int> { static constexpr int inf() { return 0x3f3f3f3f; } };
template<> struct Inf<long long> { static constexpr long long inf() { return 0x3f3f3f3f3f3f3f3fLL; } };
constexpr int INF = Inf<int>::inf(); constexpr ll BINF = Inf<ll>::inf();
// mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
// }}}
// Dinic Maximum Flow {{{
template<class T>
class Dinic {

private:

	struct edge {
		int from, to; T cap;
		edge *rev;
		edge(int u, int v, T c) : from(u), to(v), cap(c), rev(nullptr) {}
	};

	static constexpr T INF = Inf<T>::inf();

	int n, s, t;
	std::vector<std::vector<edge*>> g;

public:

	Dinic(int n, int s, int t) : n(n), s(s), t(t), g(n) {}
	~Dinic() { for (auto v : g) for (edge *e : v) delete e; }

	void addEdge(int u, int v, T c) {
		edge *in = new edge(u, v, c);
		edge *out = new edge(v, u, 0);
		g[u].push_back(in); g[v].push_back(out);
		in->rev = out; out->rev = in;
	}

	T maxFlow() {
		T mxf = 0;
		std::vector<T> dist(n, INF), vis(n);
		std::function<T(int, T)> dfs = [&] (int u, T fo) -> T {
			if (u == t) return fo;
			for (;vis[u]<int(g[u].size());vis[u]++) {
				edge *e = g[u][vis[u]];
				int v = e->to;
				if (dist[v] != dist[u] + 1 || e->cap <= 0) continue;
				T foo = dfs(v, std::min(fo, e->cap));
				if (foo > 0) {
					e->cap -= foo;
					e->rev->cap += foo;
					return foo;
				}
			}
			return 0;
		};
		for (;;) {
			for (int i=0;i<n;i++) dist[i] = INF, vis[i] = 0;
			std::queue<int> q; q.push(s); dist[s] = 0;
			while (!q.empty()) {
				int u = q.front(); q.pop();
				if (u == t) break;
				for (edge *e: g[u]) {
					int v = e->to;
					if (e->cap > 0 && dist[v] == INF) {
						dist[v] = dist[u] + 1;
						q.push(v);
					}
				}
			}
			if (dist[t] == INF) break;
			while (T fo = dfs(s, INF))
				mxf += fo;
		}
		return mxf;
	}

};
template<class T> constexpr T Dinic<T>::INF;
// }}}

int solve() {
	int n, m; cin >> n >> m;
	vvi dp(n, vi(n, INF));
	for (int i=0;i<m;i++) {
		int u, v; cin >> u >> v; u--, v--;
		dp[u][v] = dp[v][u] = 1;
	}
	for (int i=0;i<n;i++) dp[i][i] = 0;
	for (int k=0;k<n;k++) for (int i=0;i<n;i++) for (int j=0;j<n;j++)
		dp[i][j] = min(dp[i][j], dp[i][k] + dp[k][j]);

	int s, b, k; cin >> s >> b >> k;
	vi xs(s), as(s), fs(s), ps(s), xb(b), db(b), gb(b);
	for (int i=0;i<s;i++) {
		cin >> xs[i] >> as[i] >> fs[i] >> ps[i];
		xs[i]--;
	}
	for (int i=0;i<b;i++) {
		cin >> xb[i] >> db[i] >> gb[i];
		xb[i]--;
	}

	vi canGet(s);

	/*
	for (int i=0;i<s;i++) for (int j=0;j<b;j++) {
		if (dp[xs[i]][xb[j]] > fs[i]) continue;
		if (db[j] > as[i]) continue;
		canGet[i] = max(canGet[i], gb[j]);
	}
	*/

	vector<vpii> bsList(n);
	for (int i=0;i<b;i++) bsList[xb[i]].emplace_back(db[i], gb[i]);
	for (int i=0;i<n;i++) {
		sort(bsList[i].begin(), bsList[i].end());
		int z = bsList[i].size();
		for (int j=1;j<z;j++) bsList[i][j].second = max(bsList[i][j].second, bsList[i][j - 1].second);
	}
	for (int i=0;i<s;i++) for (int j=0;j<n;j++) {
		if (dp[xs[i]][j] > fs[i]) continue;
		auto it = upper_bound(bsList[j].begin(), bsList[j].end(), pii{as[i], INF});
		if (it == bsList[j].begin()) continue;
		it--;
		canGet[i] = max(canGet[i], it->second);
	}
	for (int i=0;i<s;i++) canGet[i] -= ps[i];

	ll ans = 0;
	Dinic<ll> g(s + 2, s, s + 1);
	for (int i=0;i<s;i++) {
		if (canGet[i] >= 0) {
			ans += canGet[i];
			g.addEdge(s, i, canGet[i]);
		} else {
			g.addEdge(i, s + 1, -canGet[i]);
		}
	}
	for (int i=0;i<k;i++) {
		int u, v; cin >> u >> v; u--, v--;
		g.addEdge(u, v, BINF / 2);
	}
	ans -= g.maxFlow();
	cout << ans << endl;

	return 0;
}

// Template Main {{{
int main() {
	ios::sync_with_stdio(0);
	// precompute();
	// int t; cin >> t; for (int i=1;i<=t;i++)
	solve();
	// cout << "Case #" << i << ": ", solve();
	return 0;
}

template <class T> istream &operator>>(istream &is, vector<T> &v) {
	for (auto it=v.begin();it!=v.end();++it) is >> *it;
	return is;
}

template <class T> ostream &operator<<(ostream &os, const vector<T> &v) {
	for (auto it=v.begin();it!=v.end();) os << *it, os << " \n"[++it==v.end()];
	return os;
}

template <class T, class U> istream &operator>>(istream &is, pair<T, U> &p) {
	return is >> p.first >> p.second;
}

template <class T, class U> ostream &operator<<(ostream &os, const pair<T, U> &p) {
	return os << p.first << ' ' << p.second;
}
// }}}

// vim: fdm=marker

#include <bits/stdc++.h>
using namespace std;
#define pb push_back

typedef long long ll;

#define N 105
#define M 100005
template <class T> void chkmax(T &a, T b) {if (a < b) a = b;}
//template <class T> void chkmin(T &a, T b) {if (a > b) a = b;}

vector <int> v[N];
vector <int> vs[N], vb[N];

int n, m;
int nn, mm, kk;

int f[M], d[M], g[M], a[M], x[M], y[M], p[M];

bool cmpf(int x, int y) {
	return f[x] < f[y];
}

int dd[N];

int fen[M<<1];

int val[M<<1], vals;
void update(int k, int v) {
    for ( ; k <= vals; k += k & -k) {
        chkmax(fen[k], v);
    }
    return;
}
const int inf = 0x3f3f3f3f;
int calc_mx(int k) {
	int res = -inf;
    for ( ; k; k -= k & -k) {
        chkmax(res, fen[k]);
    }
    return res;
}

void update(int k) {
    for (auto x : vb[k]) {
        update(d[x], g[x]);
    }
}

int rd[M];
void solve(int k) {
    memset(dd, -1, sizeof dd);
    memset(fen, -1, sizeof fen);
    vector <int> A, B;
    A.pb(k); int now = 0;
    update(k); int tot = 1;
    int t = 0;
    while (t < vs[k].size() && f[vs[k][t]] == 0) {
        int kk = vs[k][t];
        chkmax(rd[kk], calc_mx(a[kk]));
        t ++;
    }
    while (tot < n && t < vs[k].size()) {
		B.clear();
		now ++;
        for (auto x : A) {
            for (auto y : v[x]) {
                if (dd[y] < 0) {
					B.pb(y);
                    update(y);
                    dd[y] = dd[x] + 1;
                }
            }
        }
        tot += B.size();
        while (t < vs[k].size() && f[vs[k][t]] == now) {
            int kk = vs[k][t];
            chkmax(rd[kk], calc_mx(a[kk]));
            t ++;
        }
        A.swap(B);
    }
    while (t < vs[k].size()) {
        int kk = vs[k][t];
        chkmax(rd[kk], calc_mx(a[kk]));
        t ++;
    }
    return;
}

vector <int> vv[M];

bool vd[M], vis[M];

void dfs(int k) {
    vd[k] = 1; vis[k] = 1;
    for (auto x : vv[k]) {
        if (vd[x]) continue;
        dfs(x);
    }
    return;
}

map <int, int> H;

int tot;

const ll linf = 1e16;

struct Dinic {
	struct edge {
		int u, v;
		ll cap, flow;
		edge() {}
		edge(int u, int v, ll cap): u(u), v(v), cap(cap), flow(0) {}
	};
	int n;
	vector <edge> E;
	vector < vector <int> > g;
	vector <int> d, pt;

	Dinic(int n): n(n), E(0), g(n), d(n), pt(n) {}
	Dinic() {}
	void init(int _n) {
		n = _n;
		g.resize(n); d.resize(n);
		E.resize(0); pt.resize(n);
		for (int i = 0; i < n; i ++) g[i].clear();
	}
	void add_edge(int u, int v, ll cap) {
		if (u != v) {
			E.push_back(edge(u, v, cap));
			g[u].push_back(E.size() - 1);
			E.push_back(edge(v, u, 0));
			g[v].push_back(E.size() - 1);
		}
	}

	bool BFS(int S, int T) {
		queue<int> q;
		q.push(S);
		fill(d.begin(), d.end(), n + 1);
		d[S] = 0;
		while(!q.empty()) {
			int u = q.front(); q.pop();
			if (u == T) break;
			for (int i = 0; i < g[u].size(); i ++) {
				int k = g[u][i];
				edge &e = E[k];
				if (e.flow < e.cap && d[e.v] > d[e.u] + 1) {
					d[e.v] = d[e.u] + 1;
					q.push(e.v);
				}
			}
		}
		return d[T] != n + 1;
	}

	ll DFS(int u, int T, ll flow = -1) {
		if (u == T || flow == 0) return flow;
		for (int &i = pt[u]; i < g[u].size(); ++i) {
			edge &e = E[g[u][i]];
			edge &oe = E[g[u][i]^1];
			if (d[e.v] == d[e.u] + 1) {
				ll amt = e.cap - e.flow;
				if (flow != -1 && amt > flow) amt = flow;
				if (ll pushed = DFS(e.v, T, amt)) {
					e.flow += pushed;
					oe.flow -= pushed;
					return pushed;
				}
			}
		}
		return 0;
	}

	ll maxflow(int S, int T) {
		ll res = 0;
		while (BFS(S, T)) {
			fill(pt.begin(), pt.end(), 0);
			while (ll flow = DFS(S, T)) res += flow;
		}
		return res;
	}
} A;

ll tot_sum;

bool vvis[M];

void add_edge(int x, int y) {
	vvis[x] = vvis[y] = 1;
    if (!H.count(x)) {
        H[x] = ++ tot;
        int t = rd[x] - p[x];
        if (t < 0) A.add_edge(tot, 1, -t);
        else A.add_edge(0, tot, t), tot_sum += t;
    }
    if (!H.count(y)) {
        H[y] = ++ tot;
        int t = rd[y] - p[y];
        if (t < 0) A.add_edge(tot, 1, -t);
        else A.add_edge(0, tot, t), tot_sum += t;
    }
    A.add_edge(H[x], H[y], linf);
}

int main() {
    memset(rd, -1, sizeof rd);
	scanf("%d %d", &n, &m);
    for (int i = 1; i <= m; i ++) {
		int x, y;
		scanf("%d %d", &x, &y);
		v[x].pb(y);
		v[y].pb(x);
    }
    scanf("%d %d %d", &nn, &mm, &kk);
    for (int i = 1; i <= nn; i ++) {
        scanf("%d %d %d %d", &x[i], &a[i], &f[i], &p[i]);
        if (f[i] >= n) f[i] = n-1;
        val[vals++] = a[i];
        vs[x[i]].pb(i);
    }
    for (int i = 1; i <= mm; i ++) {
        scanf("%d %d %d", &y[i], &d[i], &g[i]);
        vb[y[i]].pb(i);
        val[vals++] = d[i];
    }
    sort(val, val+vals);
    vals = unique(val, val+vals) - val;
    for (int i = 1; i <= nn; i ++) {
        a[i] = lower_bound(val, val+vals, a[i]) - val + 1;
    }
    for (int i = 1; i <= mm; i ++) {
        d[i] = lower_bound(val, val+vals, d[i]) - val + 1;
    }
    for (int i = 1; i <= n; i ++) sort(vs[i].begin(), vs[i].end(), cmpf);
    for (int i = 1; i <= n; i ++) if (!vs[i].empty()) solve(i);
    for (int i = 1; i <= nn; i ++) if (rd[i] < 0) vis[i] = 1;
    while (kk --) {
        int x, y;
		scanf("%d %d", &x, &y);
        vv[y].pb(x);
    }
    for (int i = 1; i <= nn; i ++) if (vis[i] && !vd[i]) dfs(i);
    A.init(3000);
    tot = 1;
    for (int i = 1; i <= nn; i ++) if (!vis[i]) {
        for (auto x : vv[i]) if (!vis[x]) {
            add_edge(x, i);
        }
    }
    ll flow = A.maxflow(0, 1);
    flow = tot_sum - flow;
    for (int i = 1; i <= nn; i ++) if (!vvis[i] && !vis[i] && rd[i] - p[i] > 0) flow += rd[i] - p[i];
    printf("%I64d\n", flow);
    return 0;
}

#include <iostream>
#include <fstream>
#include <numeric>
#include <iomanip>
#include <cstring>
#include <string>
#include <algorithm>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <deque>

#define int ll
#define sz(a) (int)((a).size())
#define all(a) (a).begin(), (a).end()
#define pb push_back

using namespace std; using ll = long long; using vi = vector<int>; using pii = pair<int, int>; using ld = long double;

const ll inf = (ll)1e18 + 100;

int n, m;
int d[100][100];
int s, b, k;

struct ship {
	int x, a, f, p;
} ss[100000];

struct base {
	int x, d, g;
} bb[100000];

struct maxflow {
	struct edge {
		int to, c, f;
	};

	vector<edge> e;
	vector<vi> g;
	int N, S, T;
	vi pt, d;
	int A;

	bool bfs() {
		fill_n(d.begin(), N, inf);
		d[S] = 0;
		queue<int> q;
		q.push(S);
		while (!q.empty()) {
			int v = q.front();
			q.pop();
			for (int i : g[v]) {
				edge& ee = e[i];
				if (ee.c - ee.f >= A && d[ee.to] == inf) {
					d[ee.to] = d[v] + 1;
					q.push(ee.to);
				}
			}

		}
		return (d[T] != inf);
	}

	int dfs(int v, int cmin) {
		if (v == T) {
			return cmin;
		}
		for (; pt[v] < sz(g[v]); pt[v]++) {
			int i = g[v][pt[v]];
			edge& ee = e[i];
			if (ee.c - ee.f >= A && d[ee.to] == d[v] + 1) {
				int f = dfs(ee.to, min(cmin, ee.c - ee.f));
				if (f > 0) {
					ee.f += f;
					e[i ^ 1].f -= f;
					return f;
				}
			}
		}
		return 0;
	}

	void dinic() {
		d.resize(N);
		pt.resize(N);
		int mf = 0;
		for (A = inf; A; A >>= 1) {
			while (bfs()) {
				fill_n(pt.begin(), N, 0);
				while (dfs(S, inf));
			}
		}
	}

	void addEdge(int u, int v, int c) {
		static int i = 0;
		e.pb({ v, c, 0 });
		e.pb({ u, 0, 0 });
		g[u].pb(i);
		g[v].pb(i ^ 1);
		i += 2;
		//cout << u << ' ' << v << endl;
	}

	void zhfs(int v, vector<bool>& was) {
		was[v] = true;
		for (int i : g[v]) {
			edge& ee = e[i];
			if (ee.c - ee.f > 0 && !was[ee.to]) {
				zhfs(ee.to, was);
			}
		}
	}
};

vi g1[100000];
vector<pii> e;
bool ban[100000];
int w[100000];

void dfs(int v) {
	ban[v] = true;
	for (int to : g1[v]) if(!ban[to]) dfs(to);
}

vector<pii> pl[100];
vi pm[100];

int32_t main() {
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	//ifstream cin("in.txt");
	cin >> n >> m;
	for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) if(i != j) d[i][j] = inf;
	for (int i = 0; i < m; i++) {
		int u, v; cin >> u >> v; --u; --v; d[u][v] = d[v][u] = 1;
	}
	for (int k = 0; k < n; k++) for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
	cin >> s >> b >> k;
	for (int i = 0; i < s; i++) cin >> ss[i].x >> ss[i].a >> ss[i].f >> ss[i].p, --ss[i].x;
	for (int i = 0; i < b; i++) cin >> bb[i].x >> bb[i].d >> bb[i].g, --bb[i].x, pl[bb[i].x].pb({ bb[i].d, bb[i].g });
	for (int i = 0; i < n; i++) {
		if (pl[i].empty()) continue;
		sort(all(pl[i]));
		pm[i].resize(sz(pl[i]));
		pm[i][0] = pl[i][0].second;
		for (int j = 1; j < sz(pm[i]); j++) {
			pm[i][j] = max(pm[i][j - 1], pl[i][j].second);
		}
	}
	vi broken;
	maxflow grape;
	grape.N = s + 2;
	grape.S = grape.N - 2;
	grape.T = grape.N - 1;
	grape.g.resize(grape.N);
	vi ord(s); iota(all(ord), 0);
	sort(all(ord), [](int i, int j) { return ss[i].a < ss[j].a; });
	vi pt(n, -1);
	for (int i : ord) {
		int hi = -1;
		//for (int p = 0; p < n; p++) if (ss[i].f >= d[ss[i].x][p]) for (pii bas : pl[p]) if (ss[i].a >= bas.first) hi = max(hi, bas.second);
		// me for (int p = 0; p < n; p++) if (ss[i].f >= d[ss[i].x][p]) for (int t = 0; t < sz(pl[p]) && ss[i].a >= pl[p][t].first; t++) hi = max(hi, pm[p][t]);
 		//for (int j = 0; j < b; j++) if (ss[i].a >= bb[j].d && ss[i].f >= d[ss[i].x][bb[j].x]) hi = max(hi, bb[j].g);
		for (int p = 0; p < n; p++) if(ss[i].f >= d[ss[i].x][p]) {
			while (pt[p] + 1 < sz(pl[p]) && ss[i].a >= pl[p][pt[p] + 1].first) pt[p]++;
			if (pt[p] != -1) hi = max(hi, pm[p][pt[p]]);
		}
		if (hi == -1) broken.pb(i);
		else {
			hi -= ss[i].p;
			w[i] = hi;
			//cout << i << ' ' << w[i] << endl;
		}
	}
	for (int i = 0; i < k; i++) {
		int u, v; cin >> u >> v; --u; --v;
		g1[v].pb(u); e.pb({ u, v });
	}
	for (int u : broken) if (!ban[u]) dfs(u);
	for (int i = 0; i < n; i++) if (!ban[i]) {
		//cout << '!' << i << endl;
		int hi = w[i];
		if (hi < 0) grape.addEdge(i, grape.T, -hi);
		else if (hi > 0) grape.addEdge(grape.S, i, hi);
	}
	for (pii r : e) {
		int u = r.first, v = r.second;
		if (!ban[u] && !ban[v]) grape.addEdge(u, v, inf);
	}
	grape.dinic();
	vector<bool> was(grape.N, false);
	grape.zhfs(grape.S, was);
	ll ans = 0;
	for (int u = 0; u < s; u++) {
		if (was[u]) {
			ans += w[u];
		}
	}
	cout << ans;
}

#include <bits/stdc++.h>

#define F first
#define S second
#define MP make_pair
#define PB push_back

using namespace std;

typedef long long ll;
typedef long double ld;

const int max_n = 111, inf = 1000111222;
const int max_v = 100011;

namespace flow {

struct edge {
    int v;
    long long res_cap;

    edge() {
    }

    edge(int v, long long res_cap): v(v), res_cap(res_cap) {
    }
};

vector<edge> all;
vector<int> g[max_v];

void add_edge(int u, int v, long long cap) {
    g[u].push_back(all.size());
    all.push_back({v, cap});
    g[v].push_back(all.size());
    all.push_back({u, 0});
}

int h[max_v], num[max_v];

bool bfs(int s, int t) {
    for (int i = 0; i <= t; ++i) {
        h[i] = -1;
    }
    h[s] = 0;
    queue<int> q;
    q.push(s);
    while (!q.empty()) {
        int v = q.front();
        q.pop();
        for (int id : g[v]) {
            if (all[id].res_cap && h[all[id].v] == -1) {
                h[all[id].v] = h[v] + 1;
                q.push(all[id].v);
            }
        }
    }
    return h[t] != -1;
}

int dfs(int v, int t, int f) {
    if (v == t) {
        return f;
    }
    for (int &i = num[v]; i < g[v].size(); ++i) {
        int id = g[v][i];
        const edge &e = all[id];
        if (h[v] + 1 == h[e.v] && e.res_cap) {
            int x = dfs(e.v, t, min(1LL * f, e.res_cap));
            if (x) {
                all[id].res_cap -= x;
                all[id ^ 1].res_cap += x;
                return x;
            }
        }
    }
    return 0;
}

long long dinic(int s, int t) {
    long long res = 0;
    while (bfs(s, t)) {
        memset(num, 0, sizeof(num));
        while (int x = dfs(s, t, 2 * inf)) {
            res += x;
        }
    }
    return res;
}

}

int n, m, dist[max_n][max_n];
int c1, c2, k;
int v1[max_v], attack[max_v], fluel[max_v], cost1[max_v], a[max_v];
int v2[max_v], defend[max_v], cost2[max_v], U[max_v], V[max_v], bad[max_v];
vector<pair<int, int>> all[max_n];
vector<int> rg[max_v];

void dfs(int v) {
    bad[v] = 1;
    for (int to : rg[v]) {
        if (!bad[to]) {
            dfs(to);
        }
    }
}

int main() {
    //freopen("input_b.txt", "r", stdin);
    //freopen("output.txt", "w", stdout);
    scanf("%d%d", &n, &m);
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < n; ++j) {
            dist[i][j] = inf;
        }
        dist[i][i] = 0;
    }
    while (m--) {
        int u, v;
        scanf("%d%d", &u, &v);
        --u;
        --v;
        dist[u][v] = 1;
        dist[v][u] = 1;
    }
    for (int k = 0; k < n; ++k) {
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < n; ++j) {
                dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
            }
        }
    }
    scanf("%d%d%d", &c1, &c2, &k);
    for (int i = 0; i < c1; ++i) {
        scanf("%d%d%d%d", &v1[i], &attack[i], &fluel[i], &cost1[i]);
        --v1[i];
    }
    for (int i = 0; i < c2; ++i) {
        scanf("%d%d%d", &v2[i], &defend[i], &cost2[i]);
        --v2[i];
        all[v2[i]].push_back({defend[i], cost2[i]});
    }
    for (int i = 0; i < n; ++i) {
        sort(all[i].begin(), all[i].end());
        for (int j = 1; j < all[i].size(); ++j) {
            all[i][j].second = max(all[i][j].second, all[i][j - 1].second);
        }
    }
    for (int i = 0; i < c1; ++i) {
        a[i] = -inf;
        for (int v = 0; v < n; ++v) {
            if (dist[v1[i]][v] > fluel[i]) {
                continue;
            }
            auto it = upper_bound(all[v].begin(), all[v].end(), make_pair(attack[i], inf));
            if (it != all[v].begin()) {
                --it;
                a[i] = max(a[i], it->second);
            }
        }
        if (a[i] != -inf) {
            a[i] -= cost1[i];
        } else {
            bad[i] = 1;
        }
        //cout << i << ": " << a[i] << endl;
    }
    int s = c1, t = s + 1;
    long long ans = 0;
    for (int i = 0; i < c1; ++i) {
        if (!bad[i]) {
            flow::add_edge(s, i, inf + a[i]);
            flow::add_edge(i, t, inf);
            ans -= a[i] + inf;
        }
    }
    long long big_inf = 10001112LL * inf;
    for (int i = 0; i < k; ++i) {
        scanf("%d%d", &U[i], &V[i]);
        --U[i];
        --V[i];
        rg[V[i]].push_back(U[i]);
    }
    for (int i = 0; i < c1; ++i) {
        if (bad[i]) {
            dfs(i);
        }
    }
    for (int i = 0; i < k; ++i) {
        if (!bad[U[i]] && !bad[V[i]]) {
            flow::add_edge(U[i], V[i], big_inf);
        }
    }
    ans += flow::dinic(s, t);
    printf("%I64d\n", -ans);
    return 0;
}

//Author: Heltion
//Date: 07-31-2019
#include<bits/stdc++.h>
using namespace std;
using LL = long long;
template<typename T>void no(T s){cout << s; exit(0);}
void no(){cout << "NO"; exit(0);}
constexpr LL maxm = 120;
constexpr LL maxn = 120000;
LL d[maxm][maxm];
LL sx[maxn], a[maxn], f[maxn], p[maxn], bx[maxn], dd[maxn], g[maxn];
struct FlowEdge {
    int v, u;
    long long cap, flow = 0;
    FlowEdge(int v, int u, long long cap) : v(v), u(u), cap(cap) {}
};

struct Dinic {
    const long long flow_inf = 1e18;
    vector<FlowEdge> edges;
    vector<vector<int>> adj;
    int n, m = 0;
    int s, t;
    vector<int> level, ptr;
    queue<int> q;

    Dinic(int n, int s, int t) : n(n), s(s), t(t) {
        adj.resize(n);
        level.resize(n);
        ptr.resize(n);
    }

    void add_edge(int v, int u, long long cap) {
        edges.emplace_back(v, u, cap);
        edges.emplace_back(u, v, 0);
        adj[v].push_back(m);
        adj[u].push_back(m + 1);
        m += 2;
    }

    bool bfs() {
        while (!q.empty()) {
            int v = q.front();
            q.pop();
            for (int id : adj[v]) {
                if (edges[id].cap - edges[id].flow < 1)
                    continue;
                if (level[edges[id].u] != -1)
                    continue;
                level[edges[id].u] = level[v] + 1;
                q.push(edges[id].u);
            }
        }
        return level[t] != -1;
    }

    long long dfs(int v, long long pushed) {
        if (pushed == 0)
            return 0;
        if (v == t)
            return pushed;
        for (int& cid = ptr[v]; cid < (int)adj[v].size(); cid++) {
            int id = adj[v][cid];
            int u = edges[id].u;
            if (level[v] + 1 != level[u] || edges[id].cap - edges[id].flow < 1)
                continue;
            long long tr = dfs(u, min(pushed, edges[id].cap - edges[id].flow));
            if (tr == 0)
                continue;
            edges[id].flow += tr;
            edges[id ^ 1].flow -= tr;
            return tr;
        }
        return 0;
    }

    long long flow() {
        long long f = 0;
        while (true) {
            fill(level.begin(), level.end(), -1);
            level[s] = 0;
            q.push(s);
            if (!bfs())
                break;
            fill(ptr.begin(), ptr.end(), 0);
            while (long long pushed = dfs(s, flow_inf)) {
                f += pushed;
            }
        }
        return f;
    }
};
bool vis[maxn];
vector<pair<LL, LL>> v[maxn];
int main(){
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	cout.tie(nullptr);
	cout << fixed << setprecision(20);
	LL n, m;
	cin >> n >> m;
	for(LL i = 1; i <= n; i += 1)
		for(LL j = 1; j <= n; j += 1) if(i != j) d[i][j] = 1e10;
	for(LL i = 1; i <= m; i += 1){
		LL u, v;
		cin >> u >> v;
		if(u != v) d[u][v] = d[v][u] = 1;
	}
	for(LL k = 1; k <= n; k += 1)
		for(LL i = 1; i <= n; i += 1)
			for(LL j = 1; j <= n; j += 1)
				d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
	LL s, b, k;
	cin >> s >> b >> k;
	LL ans = 0;
	for(LL i = 1; i <= s; i += 1)
		cin >> sx[i] >> a[i] >> f[i] >> p[i];
	for(LL i = 1; i <= b; i += 1)
		cin >> bx[i] >> dd[i] >> g[i];

	Dinic dinic(2 * s + 2, 0, 2 * s + 1);
	for(LL i = 1; i <= k; i += 1){
		int u, v;
		cin >> u >> v;
		dinic.add_edge(u, 2 * v, 1e18);
		vis[u] = vis[v] = true;
	}
	for(LL j = 1; j <= b; j += 1)
		v[bx[j]].push_back(make_pair(dd[j], g[j]));
	for(LL j = 1; j <= n; j += 1){
		sort(v[j].begin(), v[j].end());
		for(LL i = 1; i < (LL)v[j].size(); i += 1)
			v[j][i].second = max(v[j][i].second, v[j][i - 1].second);
	}
	for(LL i = 1; i <= s; i += 1){
		LL x = -1e15;
		for(LL j = 1; j <= n; j += 1)
			if(d[sx[i]][j] <= f[i]) {
				auto p = upper_bound(v[j].begin(), v[j].end(), make_pair(a[i], (LL)1e18));
				if(p == v[j].begin()) continue;
				p --;
				x = max(x, p->second);
			}
		if(vis[i]){
			dinic.add_edge(i, 2 * s + 1, p[i]);
			if(x >= 0){
				ans += x;
				dinic.add_edge(0, 2 * i, x);
			}
			else dinic.add_edge(2 * i, 2 * s + 1, -x);
			dinic.add_edge(2 * i, i, 1e18);
		}
		else ans += max(0LL, x - p[i]);
	}
	cout << ans - dinic.flow();
	return 0;
}

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;

struct brod {
	int x, a, p, i;
	ll f;
};

struct baza {
	int x, d,    g;
};

int d[105][105];
int n, m;

struct dependency {
	int u, v;
};

brod a[100005];
baza c[100005];

vector<pair<int, ll>> zlato[105];
int zlato_ptr[105];

dependency dep[1005];
int ugly[100005];
// drugi graf za analizu (scc)
ll p2[2005]; int s2;
basic_string<int> df[2005];
bool reach[2005][2005];

void dfs2(int x, bool* reach) {
	reach[x] = true;
	for (int y : df[x]) {
		if (!reach[y]) {
			dfs2(y, reach);
		}
	}
}
// treci graf
int s3;
int c3[2005];
ll p3[2005];
basic_string<int> e3[2005];

// cetvrti graf
const ll LINF = 1'000'000'000'000'000'000ll;
struct maxflow {
	struct grana {
		int v; ll c, f; int nx;
	};

	vector<grana> g;
	vector<int> start, used, d;

	maxflow(int n) : start(n, -1), used(n, -1), d(n, -1) {}

	void add_edge(int u, int v, ll c) {
		g.push_back({v, c, 0, start[u]});
		start[u] = g.size()-1;
		g.push_back({u, 0, 0, start[v]});
		start[v] = g.size()-1;
	}

	bool bfs(int s, int t) {
		basic_string<int> q = {s};
		size_t qs = 0;
		fill(d.begin(), d.end(), -1);
		d[s] = 0;
		while (qs != q.size()) {
			int x = q[qs++];
			for (int i=start[x]; i!=-1; i=g[i].nx) {
				int y = g[i].v;
				if (d[y] == -1 && g[i].c > g[i].f) {
					d[y] = d[x] + 1;
					q += y;
				}
			}
		}
		return d[t] != -1;
	}

	ll dfs(int x, int t, ll f=LINF) {
		if (x == t)
			return f;
		for (int& i=used[x]; i!=-1; i=g[i].nx) {
			int y = g[i].v;
			if (d[y] == d[x]+1 && g[i].c > g[i].f) {
				ll z = dfs(y, t, min(f, g[i].c - g[i].f));
				if (z > 0) {
					g[i].f += z;
					g[i^1].f -= z;
					return z;
				}
			}
		}
		return 0;
	}

	ll flow(int s, int t) {
		ll z = 0;
		while (bfs(s, t)) {
			used = start;
			while (1) {
				ll f = dfs(s, t);
				if (f > 0) {
					z += f;
				} else {
					break;
				}
			}
		}
		return z;
	}
};

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(nullptr);
	cout.tie(nullptr);
	cerr.tie(nullptr);

	cin >> n >> m;
	memset(d, 63, sizeof(d));
	for (int i=1; i<=n; i++)
		d[i][i] = 0;
	for (int i=0; i<m; i++) {
		int u, v;
		cin >> u >> v;
		if (u != v) {
			d[u][v] = 1;
			d[v][u] = 1;
		}
	}
	for (int i=1; i<=n; i++)
		for (int j=1; j<=n; j++)
			for (int k=1; k<=n; k++)
				d[j][k] = min(d[j][k], d[j][i] + d[i][k]);

	int s, b, k;
	cin >> s >> b >> k;
	for (int i=0; i<s; i++) {
		cin >> a[i].x >> a[i].a >> a[i].f >> a[i].p;
		a[i].i = i;
	}
	for (int i=0; i<b; i++) {
		cin >> c[i].x >> c[i].d >> c[i].g;
		zlato[c[i].x].emplace_back(c[i].d, c[i].g);
	}
	for (int i=1; i<=n; i++) {
		sort(zlato[i].begin(), zlato[i].end());
		zlato[i].emplace_back(2e9, 0);
		ll z = 0;
		for (auto& [x, y] : zlato[i]) {
			ll t = z;
			z = max(z, y);
			y = t;
		}
	}
	sort(a, a+s, [&](brod u, brod v) { return u.a < v.a; });
	for (int i=0; i<s; i++) {
		ll profit = -1e10;
		for (int x=1; x<=n; x++) {
			if (d[a[i].x][x] > a[i].f)
				continue;

			while (zlato[x][zlato_ptr[x]].first <= a[i].a)
				zlato_ptr[x]++;
			profit = max(profit, zlato[x][zlato_ptr[x]].second - a[i].p);
		}
		a[i].f = profit;
	}
	sort(a, a+s, [&](brod u, brod v) { return u.i < v.i; });
	// for (int i=0; i<s; i++)
		// cerr << i << " profit " << a[i].f << '\n';

	for (int i=0; i<k; i++) {
		cin >> dep[i].u >> dep[i].v;
		dep[i].u--;
		dep[i].v--;
		ugly[dep[i].u] = ugly[dep[i].v] = 1;
	}

	ll extra = 0;

	for (int i=0; i<s; i++) {
		if (ugly[i]) {
			ugly[i] = ++s2;
			p2[s2] = a[i].f;
		} else {
			extra += max(0ll, a[i].f);
		}
	}

	for (int i=0; i<k; i++) {
		df[ugly[dep[i].u]] += ugly[dep[i].v];
	}

	for (int i=1; i<=s2; i++) {
		dfs2(i, reach[i]);
	}

	for (int i=1; i<=s2; i++) {
		if (c3[i] == 0) {
			s3++;
			for (int j=1; j<=s2; j++) {
				if (reach[i][j] && reach[j][i]) {
					c3[j] = s3;
					p3[s3] += p2[j];
				}
			}
		}
	}

	for (int i=1; i<=s2; i++)
		for (int j : df[i])
			if (c3[i] != c3[j])
				e3[c3[i]] += c3[j];

	for (int i=1; i<=s3; i++) {
		sort(e3[i].begin(), e3[i].end());
		e3[i].resize(unique(e3[i].begin(), e3[i].end()) - e3[i].begin());
	}

	// flow?
	maxflow mf(s3+2);
	int source = 0;
	int sink = s3+1;
	for (int i=1; i<=s3; i++) {
		// cerr << "objekat " << i << " profita " << p3[i] << '\n';
		if (p3[i] < 0) {
			mf.add_edge(i, sink, -p3[i]);
		} else if (p3[i] > 0) {
			mf.add_edge(source, i, p3[i]);
			extra += p3[i];
		}
	}

	for (int i=1; i<=s3; i++)
		for (int j : e3[i]) {
			// cerr << i << " zavisi od " << j << '\n';
			mf.add_edge(i, j, LINF);
		}

	ll fl = mf.flow(source, sink);
	// cerr << "flow: " << fl << '\n';

	cout << extra - fl << '\n';
}

#include <bits/stdc++.h>
//
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 100015;
const int maxm = 1000005;
int g[105][105];
int num[maxn];
int cnt;
void floyed(int n){
    for(int k = 1; k <= n; k++){
        for(int i = 1; i <= n; i++){
            for(int j = 1; j <= n; j++){
                g[i][j] = min(g[i][j], g[i][k]+g[k][j]);
            }
        }
    }
};
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
    while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
struct Edge{
    int to,next,cap,flow;
}edge[maxm];
int tol,head[maxn];
void init()
{
    tol=2;
    memset(head,-1,sizeof(head));
}
void addedge(int u,int v,int w,int rw=0)
{
    edge[tol].to=v;edge[tol].cap=w;edge[tol].flow=0;
    edge[tol].next=head[u];head[u]=tol++;
    edge[tol].to=u;edge[tol].cap=rw;edge[tol].flow=0;
    edge[tol].next=head[v];head[v]=tol++;
}
int Q[maxn];
int dep[maxn],cur[maxn],sta[maxn];
bool bfs(int s,int t,int n)
{
    int front=0,tail=0;
    memset(dep,-1,sizeof(dep[0])*(n+1));
    dep[s]=0;
    Q[tail++]=s;
    while(front<tail){
        int u=Q[front++];
        for(int i=head[u];i!=-1;i=edge[i].next){
            int v=edge[i].to;
            if(edge[i].cap>edge[i].flow&&dep[v]==-1){
                dep[v]=dep[u]+1;
                if(v==t){
                    return true;
                }
                Q[tail++]=v;
            }
        }
    }
    return false;
}
long long dinic(int s,int t,int n)
{
    long long maxflow=0;
    while(bfs(s,t,n)){
        for(int i=0;i<n;i++){
            cur[i]=head[i];
        }
        int u=s,tail=0;
        while(cur[s]!=-1){
            if(u==t){
                int tp=INF;
                for(int i=tail-1;i>=0;i--){
                    tp=min(tp,edge[sta[i]].cap-edge[sta[i]].flow);
                }
                maxflow+=tp;
                for(int i=tail-1;i>=0;i--){
                    edge[sta[i]].flow+=tp;
                    edge[sta[i]^1].flow-=tp;
                    if(edge[sta[i]].cap-edge[sta[i]].flow==0){
                        tail=i;
                    }
                }
                u=edge[sta[tail]^1].to;
            }else if(cur[u]!=-1&&edge[cur[u]].cap>edge[cur[u]].flow&&dep[u]+1==dep[edge[cur[u]].to]){
                sta[tail++]=cur[u];
                u=edge[cur[u]].to;
            }else{
                while(u!=s&&cur[u]==-1){
                    u=edge[sta[--tail]^1].to;
                }
                cur[u]=edge[cur[u]].next;
            }
        }
    }
    return maxflow;
}
//vector<int>fuck[100005];
int fuckacm[100005];
int ps[105];
int in[maxn], out[maxn], shipos[maxn], atk[maxn], f[maxn], p[maxn], baspos[maxn], d[maxn], gold[maxn], val[maxn];
bool svis[maxn];
#define pii pair<int,int>
vector<pii> v1[105];
int main(){
    int n, m, u, v, s, b, k;
    n = read(), m = read();
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n; j++){
            if(i==j) g[i][j] = 0;
            else g[i][j] = g[j][i] = INF;
        }
    }
    for(int i = 1; i <= m; i++){
        u = read(), v = read();
        g[u][v] = g[v][u] = 1;
    }
    floyed(n);
    s = read(), b = read(), k = read();
    for(int i = 1; i <= s; i++){
        shipos[i] = read(), atk[i] = read(), f[i] = read(), p[i] = read();
    }
    for(int i = 1; i <= b; i++){
        baspos[i] = read(), d[i] = read(), gold[i] = read();
        v1[baspos[i]].emplace_back(pii(d[i], gold[i]));
    }
    for(int i = 1; i <= k; i++){
        int tmp1, tmp2;
        tmp1 = read(), tmp2 = read();
        fuckacm[tmp1] = tmp2;
        in[tmp2]++, out[tmp1]++;
    }
    for(int i = 1; i <= s; i++){
        int ma = -INF;
        for(int j = 1; j <= n; j++){
            if(g[shipos[i]][j] <= f[i]){
                if(v1[j].empty()) continue;
                while(ps[j] < v1[j].size()-1 && v1[j][ps[j]+1].first <= atk[i]) ps[j]++;
                if(v1[j][ps[j]].first <= atk[i]) ma = max(ma, v1[j][ps[j]].second);
            }
        }
        val[i] = ma-p[i];
    }
    long long ans = 0;
    for(int i = 1; i <= s; i++){
        if(in[i] == 0 && out[i] > 0){
            if(val[i] <= 0){
                svis[i] = true;
            }
        }
        if(in[i] == 0 && out[i] == 0 && val[i]>0){
            ans += val[i];
            svis[i] = true;
        }
        if(in[i] == 0 && out[i] == 0 && val[i] < 0){
            svis[i] = true;
        }
    }
    int S = 2015+1, T = S+1;
    init();
    for(int i = 1; i <= s; i++){
        if(!svis[i]){
            if(val[i] > 0){
                num[i] = ++cnt;
                addedge(S, cnt, val[i]);
                ans += val[i];
            }
            else{
                num[i] = ++cnt;
                addedge(cnt, T, -val[i]);
            }
        }
    }
    for(int i = 1; i <= s; i++){
        if(!svis[i] && val[i] > 0)
            addedge(num[i], num[fuckacm[i]], INF);
    }
    ans -= dinic(S, T, T+1);
    cout << ans;
    return 0;
}

#include<bits/stdc++.h>
using namespace std;

const int MAXN=3000+5,MAXM=10000+10;
const long long int INF = 1e15;
bool visit[MAXN];
int head[MAXN],dist[MAXN],stamp,tmphead[MAXN];
struct EDGE{
   int to;
   long long int r;
   int next;
}edge[MAXM*2];
void init(){
   stamp=0;
   memset(head,-1,sizeof head);
}
void addedge(int a,int b,long long int c){
   edge[stamp]={b,c,head[a]};
   head[a]=stamp++;
   edge[stamp]={a,0,head[b]};
   head[b]=stamp++;
}
int BFS(int s,int t){
   for(int i=0;i<=t;i++)//The nodes being used
      dist[i]=1e9;
   memset(visit,0,sizeof visit);
   queue<int> q;
   q.push(s);dist[s]=0;visit[s]=true;
   while(!q.empty()){
      int now=q.front();q.pop();
      for(int i=head[now];i!=-1;i=edge[i].next){
         int nextnode=edge[i].to;
         if(edge[i].r>0&&!visit[nextnode]){
            dist[nextnode]=dist[now]+1;
            visit[nextnode]=true;
            q.push(nextnode);
            if(nextnode==t)   return dist[t];
         }
      }
   }
   return -1;
}
long long int DFS(int now,long long int df,int t){
   if(now==t)  return df;
   visit[now]=true;
   for(int i=tmphead[now];i!=-1;tmphead[now]=i=edge[i].next){
      int nextnode=edge[i].to;
      if(edge[i].r>0&&dist[now]+1==dist[nextnode]&&!visit[nextnode]){
         long long int f=DFS(nextnode,min(df,edge[i].r),t);
         if(f){
            edge[i].r-=f;
            edge[i^1].r+=f;
            return f;
         }
      }
   }
   return 0;
}
long long int Dinic(int s,int t){
   long long int flow=0;
   while(BFS(s,t)!=-1){
      memcpy(tmphead,head,sizeof head);
      while(true){
         memset(visit,0,sizeof visit);
         long long int f=DFS(s,INF,t);
         if(!f)   break;
         flow+=f;
      }
   }
   return flow;
}

int dp[101][101];
struct SP{
	int x,a,f,p,pro,idx;
	bool operator<(const SP& rhs)const{
		return a<rhs.a;
	}
}sp[100001];

struct BA{
	int x,d,g;
	bool operator<(const BA& rhs)const{
		return d<rhs.d;
	}
}ba[100001];
int cur[101];
int s1[1001],s2[1001];
map<int,int> mp;
set<int> st;
int main(){
	ios_base::sync_with_stdio(0);
	cin.tie(0);
	int n,m;
	cin>>n>>m;
	init();
	for(int i=1;i<=100;i++)
		cur[i]=-1e9;
	for(int i=1;i<=100;i++)
		for(int j=1;j<=100;j++)
			dp[i][j]=1e9+1;
	for(int i=1,u,v;i<=m;i++){
		cin>>u>>v;
		dp[u][v]=dp[v][u]=1;
	}
	for(int i=1;i<=100;i++)
		dp[i][i]=0;
	for(int k=1;k<=n;k++)
		for(int i=1;i<=n;i++)
			for(int j=1;j<=n;j++)
				dp[i][j]=min(dp[i][j],dp[i][k]+dp[k][j]);
	int s,b,k;
	cin>>s>>b>>k;
	for(int i=1;i<=s;i++){
		cin>>sp[i].x>>sp[i].a>>sp[i].f>>sp[i].p;
		sp[i].pro=-1e9-1;
		sp[i].idx=i;
	}
	sort(sp+1,sp+s+1);
	for(int i=1;i<=b;i++){
		cin>>ba[i].x>>ba[i].d>>ba[i].g;
	}
	sort(ba+1,ba+b+1);
	int pb=1;
	for(int i=1;i<=s;i++){
		while(pb<=b&&ba[pb].d<=sp[i].a)
			cur[ba[pb].x]=max(cur[ba[pb].x],ba[pb].g),pb++;
		for(int j=1;j<=n;j++)
			if(dp[j][sp[i].x]<=sp[i].f)
				sp[i].pro=max(sp[i].pro,cur[j]);
	}
	for(int i=1;i<=k;i++){
		cin>>s1[i]>>s2[i];
		st.insert(s1[i]);st.insert(s2[i]);
	}
	int stp=0;
	for(int it:st)
		mp[it]=++stp;
	long long int ans=0;
	for(int i=1;i<=s;i++){
		sp[i].pro-=sp[i].p;
		if(sp[i].pro>=0)	ans+=sp[i].pro;
		if(mp.find(sp[i].idx)!=mp.end()){
			if(sp[i].pro>0)
				addedge(stp+1,mp[sp[i].idx],sp[i].pro);
			else if(sp[i].pro<0)
					addedge(mp[sp[i].idx],stp+2,(sp[i].pro<-1e9?INF:-sp[i].pro));
		}
	}
	for(int i=1;i<=k;i++)
		addedge(mp[s1[i]],mp[s2[i]],INF);
	cout<<ans-Dinic(stp+1,stp+2)<<endl;
}

#include<bits/stdc++.h>

using namespace std;

#define double long double

typedef pair<int,int> ii;
typedef pair<int,long long> il;
typedef pair<long long,long long> ll;
typedef pair<ll,int> lli;
typedef pair<long long,int> li;
typedef pair<double,double> dd;
typedef pair<ii,int> iii;
typedef pair<double,int> di;
typedef pair<int,ii> iii2;
typedef pair<ii,ii> iiii;
typedef vector<int> vi;
long long mod = 1000000007LL;
long long large = 2000000000000000000LL;

struct Edge {
	int from,to;
	long long cap,flow;
};

struct Dinic {
	int n,m,s,t;
	vector<Edge> edges;
	vector<vector<int> > G;
	vector<bool> vis;
	vector<int> dis;
	vector<int> cur;
	void init(int maxn){
		edges.clear();
		G.assign(maxn+10,vector<int>(0));
		vis.assign(maxn+10,false);
		dis.assign(maxn+10,0);
		cur.assign(maxn+10,0);
		n=maxn;
	}
	void addEdge(int from,int to,long long cap){
		edges.push_back((Edge){from,to,cap,0});
		edges.push_back((Edge){to,from,0,0});
		m=edges.size();
		G[from].push_back(m-2);
		G[to].push_back(m-1);
	}
	bool BFS() {
		vis.assign(n+10,false);
		queue<int> q;
		q.push(s);
		dis[s]=0;
		vis[s]=true;
		while(!q.empty()){
			int u=q.front();
			q.pop();
			for(int i=0;i<(int)G[u].size();i++){
				Edge& e=edges[G[u][i]];
				if(!vis[e.to]&&e.cap>e.flow){
					vis[e.to]=1;
					dis[e.to]=dis[u]+1;
					q.push(e.to);
				}
			}
		}
		return vis[t];
	}
	long long DFS(int x,long long a){
		if(x==t||a==0) return a;
		long long flow=0,f;
		for(int& i=cur[x];i<(int)G[x].size();i++){
			Edge& e=edges[G[x][i]];
			if(dis[x]+1==dis[e.to]&&(f=DFS(e.to,min(a,e.cap-e.flow)))>0){
				e.flow+=f;
				edges[G[x][i]^1].flow-=f;
				flow+=f;
				a-=f;
				if(a==0) break;
			}
		}
		return flow;
	}
	long long maxflow(int s,int t){
		this->s=s;
		this->t=t;
		long long flow=0;
		while(BFS()){
			cur.assign(n+10,0);
			flow+=DFS(s,large);
		}
		return flow;
	}
	void clearflow(){
		vis.assign(n+10,false);
		dis.assign(n+10,0);
		cur.assign(n+10,0);
		for(int i=0;i<(int)edges.size();i++){
			edges[i].flow=0;
		}
	}
};

int main(){

	int n,m;
	cin>>n>>m;
	vector<vector<int> > g(n,vector<int>(n,1000000000));
	for(int i=0;i<m;i++){
		int x,y;
		cin>>x>>y;
		x--;y--;
		g[x][y] = g[y][x] =1;
	}

	for(int i=0;i<n;i++) g[i][i] = 0;
	for(int k=0;k<n;k++) for(int i=0;i<n;i++) for(int j=0;j<n;j++) g[i][j] = min(g[i][j],g[i][k]+g[k][j]);

	int s,b;
	cin>>s>>b;

	int k;
	cin>>k;

	vector<int> ps(s,0),a(s,0),f(s,0),p(s,0);
	vector<int> pb(b,0),d(b,0),gold(b,0);
	for(int i=0;i<s;i++){
		cin>>ps[i]>>a[i]>>f[i]>>p[i];
		ps[i]--;
	}
	for(int i=0;i<b;i++){
		cin>>pb[i]>>d[i]>>gold[i];
		pb[i]--;
	}

	vector<vector<ii> > adj(n,vector<ii>());
	for(int i=0;i<b;i++){
		adj[pb[i]].push_back(ii(d[i],gold[i]));
	}
	for(int i=0;i<n;i++) sort(adj[i].begin(),adj[i].end());
	for(int i=0;i<n;i++){
		for(int j=0;j<(int)adj[i].size();j++){
			if(j) adj[i][j].second = max(adj[i][j].second,adj[i][j-1].second);
		}
	}

	for(int i=0;i<s;i++){
		int ans = 0;
		for(int j=0;j<n;j++){
			if(g[ps[i]][j]>f[i]) continue;
			int pt = upper_bound(adj[j].begin(),adj[j].end(),ii(a[i],1000000010))-adj[j].begin();
			pt--;
			if(pt>=0) ans = max(ans,adj[j][pt].second);
		}
		p[i] = ans-p[i];
	}

	Dinic din;
	din.init(s+10);
	int st = s;
	int en = st+1;
	long long sum = 0;
	for(int i=0;i<s;i++){
		if(p[i]>0){
			din.addEdge(st,i,p[i]);
			sum+=p[i];
		}else din.addEdge(i,en,-p[i]);
	}

	for(int i=0;i<k;i++){
		int x,y;
		cin>>x>>y;
		x--;y--;
		din.addEdge(x,y,large);
	}

	cout<<sum-din.maxflow(st,en)<<endl;

    return 0;
}

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int INF = 1e18;
const int maxn = 100015;
const int maxm = 1000005;
int g[105][105];
int num[maxn];
int id[maxn];
int cnt;
void floyed(int n){
    for(int k = 1; k <= n; k++){
        for(int i = 1; i <= n; i++){
            for(int j = 1; j <= n; j++){
                g[i][j] = min(g[i][j], g[i][k]+g[k][j]);
            }
        }
    }
};
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
    while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
struct Edge{
    int to,next,cap,flow;
}edge[maxm];
int tol,head[maxn];
void init()
{
    tol=2;
    memset(head,-1,sizeof(head));
}
void addedge(int u,int v,int w,int rw=0)
{
    edge[tol].to=v;edge[tol].cap=w;edge[tol].flow=0;
    edge[tol].next=head[u];head[u]=tol++;
    edge[tol].to=u;edge[tol].cap=rw;edge[tol].flow=0;
    edge[tol].next=head[v];head[v]=tol++;
}
int Q[maxn];
int dep[maxn],cur[maxn],sta[maxn];
bool bfs(int s,int t,int n)
{
    int front=0,tail=0;
    memset(dep,-1,sizeof(dep[0])*(n+1));
    dep[s]=0;
    Q[tail++]=s;
    while(front<tail){
        int u=Q[front++];
        for(int i=head[u];i!=-1;i=edge[i].next){
            int v=edge[i].to;
            if(edge[i].cap>edge[i].flow&&dep[v]==-1){
                dep[v]=dep[u]+1;
                if(v==t){
                    return true;
                }
                Q[tail++]=v;
            }
        }
    }
    return false;
}
long long dinic(int s,int t,int n)
{
    long long maxflow=0;
    while(bfs(s,t,n)){
        for(int i=0;i<n;i++){
            cur[i]=head[i];
        }
        int u=s,tail=0;
        while(cur[s]!=-1){
            if(u==t){
                int tp=INF;
                for(int i=tail-1;i>=0;i--){
                    tp=min(tp,edge[sta[i]].cap-edge[sta[i]].flow);
                }
                maxflow+=tp;
                for(int i=tail-1;i>=0;i--){
                    edge[sta[i]].flow+=tp;
                    edge[sta[i]^1].flow-=tp;
                    if(edge[sta[i]].cap-edge[sta[i]].flow==0){
                        tail=i;
                    }
                }
                u=edge[sta[tail]^1].to;
            }else if(cur[u]!=-1&&edge[cur[u]].cap>edge[cur[u]].flow&&dep[u]+1==dep[edge[cur[u]].to]){
                sta[tail++]=cur[u];
                u=edge[cur[u]].to;
            }else{
                while(u!=s&&cur[u]==-1){
                    u=edge[sta[--tail]^1].to;
                }
                cur[u]=edge[cur[u]].next;
            }
        }
    }
    return maxflow;
}
//vector<int>fuck[100005];
int fuckacm[100005];
int ps[105];
int in[maxn], out[maxn], shipos[maxn], atk[maxn], f[maxn], p[maxn], baspos[maxn], d[maxn], gold[maxn], val[maxn];
bool svis[maxn];
#define pii pair<int,int>
vector<pii> v1[105];
bool cmp(int x, int y){
    return atk[x] < atk[y];
}
signed main(){
    int n, m, u, v, s, b, k;
    n = read(), m = read();
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n; j++){
            if(i==j) g[i][j] = 0;
            else g[i][j] = g[j][i] = INF;
        }
    }
    for(int i = 1; i <= m; i++){
        u = read(), v = read();
        g[u][v] = g[v][u] = 1;
    }
    floyed(n);
    s = read(), b = read(), k = read();
    for(int i = 1; i <= s; i++){
        shipos[i] = read(), atk[i] = read(), f[i] = read(), p[i] = read();
        id[i] = i;
    }
    sort(id+1, id+1+s, cmp);
    for(int i = 1; i <= b; i++){
        baspos[i] = read(), d[i] = read(), gold[i] = read();
        v1[baspos[i]].emplace_back(pii(d[i], gold[i]));
    }
    for(int i = 1; i <= k; i++){
        int tmp1, tmp2;
        tmp1 = read(), tmp2 = read();
        fuckacm[tmp1] = tmp2;
        in[tmp2]++, out[tmp1]++;
    }
    for(int i = 1; i <= n; i++){
        sort(v1[i].begin(), v1[i].end()); ps[i] = 0;
        for(int j = 1; j < v1[i].size(); j++){
            v1[i][j].second = max(v1[i][j].second, v1[i][j-1].second);
        }
    }
    for(int I = 1; I <= s; I++){
        int i = id[I];
        int ma = -INF;
        bool flag = false;
        for(int j = 1; j <= n; j++){
            if(g[shipos[i]][j] <= f[i]){
                if(v1[j].empty()) continue;
                while(ps[j] < v1[j].size()-1 && v1[j][ps[j]+1].first <= atk[i]) ps[j]++;
                if(v1[j][ps[j]].first <= atk[i]) ma = max(ma, v1[j][ps[j]].second), flag = true;
            }
        }
        if(!flag) svis[i] = true;
        val[i] = ma-p[i];
    }
    long long ans = 0;
    for(int i = 1; i <= s; i++){
        if(in[i] == 0 && out[i] > 0 && !svis[i]){
            if(val[i] <= 0){
                svis[i] = true;
            }
        }
        if(in[i] == 0 && out[i] == 0 && val[i]>0 && !svis[i]){
            ans += val[i];
            svis[i] = true;
        }
        if(in[i] == 0 && out[i] == 0 && val[i] < 0 && !svis[i]){
            svis[i] = true;
        }
    }
    int S = 2015+1, T = S+1;
    init();
    for(int i = 1; i <= s; i++){
        if(!svis[i]){
            if(val[i] > 0){
                num[i] = ++cnt;
                addedge(S, cnt, val[i]);
                ans += val[i];
            }
            else{
                num[i] = ++cnt;
                addedge(cnt, T, -val[i]);
            }
        }
    }
    for(int i = 1; i <= s; i++){
        if(!svis[i] && val[i] > 0)
            addedge(num[i], num[fuckacm[i]], INF);
    }
    ans -= dinic(S, T, T+1);
    cout << ans;
    return 0;
}

#include<bits/stdc++.h>
#define re register
#define inc(i,j,k) for(re int i=j;i<=k;i++)
#define dec(i,j,k) for(re int i=j;i>=k;i--)
#define ll long long
using namespace std;
const int MAXN=105;
const int MAXM=100005;
const int inf=2147483647;
inline int read(){
	int x=0,f=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while('0'<=ch&&ch<='9'){x=x*10+ch-'0',ch=getchar();}
	return f*x;
}
int n,m,s,b,dis[MAXN][MAXN],a,c,x,f,p,val,d,g,dp[MAXM],ru[MAXM],cnt=1,head[MAXM],t,S,T,dep[MAXM],tmp;
ll ans;
inline void floyd(){
	inc(k,1,n){
		inc(i,1,n){
			inc(j,1,n) dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
		}
	}
}
struct spaceship{
	int a,f,p,val,num;
	bool flag;
	spaceship(int aa,int ff,int pp,int vval,bool fflag,int nnum){a=aa,f=ff,p=pp,val=vval,flag=fflag,num=nnum;}
};
struct castal{
	int d,g;
	castal(int dd,int gg){d=dd,g=gg;}
};
vector<spaceship> ship[MAXN];
vector<castal> cas[MAXN],cass[MAXN];
bool cmp1(spaceship x,spaceship y){return x.a<y.a;}
bool cmp2(castal x,castal y){return x.d<y.d;}
struct egde{
	int to,nxt,flow;
}e[MAXM<<2];
bool use[MAXM];
inline void add(int a,int b,int c){
	e[++cnt].to=b;
	e[cnt].nxt=head[a];
	head[a]=cnt;
	e[cnt].flow=c;
}
bool bfs(){
	queue<int> q;
	inc(i,0,s+1) dep[i]=-1;
	q.push(S),dep[S]=1;
	while(q.size()){
		int u=q.front();
		q.pop();
		for(re int i=head[u];i;i=e[i].nxt){
			int v=e[i].to;
			if(dep[v]==-1&&e[i].flow){
				dep[v]=dep[u]+1;
				q.push(v);
			}
		}
	}
	return dep[T]!=-1;
}
ll dfs(int u,int f){
	if(u==T) return f;
	int res=f,k=0;
	for(re int i=head[u];i;i=e[i].nxt){
		int v=e[i].to;
		if(dep[u]+1==dep[v]&&e[i].flow){
			k=dfs(v,min(f,e[i].flow));
			if(!k) dep[v]=-1;
			e[i].flow-=k;
			e[i^1].flow+=k;
			res-=k;
		}
	}
	return f-res;
}
int main(){
	n=read(),m=read();
	inc(i,1,n){
		inc(j,1,n) dis[i][j]=1000;
	}
	inc(i,1,m){
		a=read(),c=read();
		dis[c][a]=dis[a][c]=1;
	}
	floyd();
	s=read(),b=read(),t=read();
	S=0,T=s+1;
	inc(i,1,s){
		x=read(),a=read(),f=read(),p=read();
		ship[x].push_back(spaceship(a,f,p,0,0,i));
	}
	inc(i,1,b){
		x=read(),d=read(),g=read();
		cas[x].push_back(castal(d,g));
	}
	inc(i,1,n) sort(ship[i].begin(),ship[i].end(),cmp1);
	inc(i,1,n) sort(cas[i].begin(),cas[i].end(),cmp2);
	inc(i,1,n){
		for(re int j=0;j<cas[i].size();j++){
			while(j<cas[i].size()&&cass[i].size()&&cas[i][j].g<cass[i][cass[i].size()-1].g) j++;
			if(j>=cas[i].size()) break;
			cass[i].push_back(cas[i][j]);
		}
	}
	inc(i,1,n){
		inc(j,1,n){
			if(!cass[j].size()) continue;
			int l=-1;
			for(re int k=0;k<ship[i].size();k++){
				while(l+1<cass[j].size()&&cass[j][l+1].d<=ship[i][k].a) l++;
				if(l!=-1&&ship[i][k].f>=dis[i][j]) ship[i][k].flag=1,ship[i][k].val=max(ship[i][k].val,cass[j][l].g);
			}
		}
	}
	inc(i,1,n){
		for(re int j=0;j<ship[i].size();j++){
			use[ship[i][j].num]=ship[i][j].flag;
			if(use[i]) dp[ship[i][j].num]=ship[i][j].val-ship[i][j].p;
			else dp[ship[i][j].num]=-inf;
			ans+=max((ll)0,(ll)dp[ship[i][j].num]);
		}
	}
	inc(i,1,t){
		a=read(),c=read();
		add(a,c,inf),add(c,a,0);
	}
	inc(i,1,s){
		if(dp[i]>0) add(S,i,dp[i]),add(i,S,0);
		else if(dp[i]<0) add(i,T,-dp[i]),add(T,i,0);
	}
	while(bfs()) while(tmp=dfs(S,inf)) ans-=(ll)tmp;
	printf("%I64d",ans);
}

#include <bits/stdc++.h>
//
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 100015;
const int maxm = 1000005;
int g[105][105];
int num[maxn];
int cnt;
void floyed(int n){
    for(int k = 1; k <= n; k++){
        for(int i = 1; i <= n; i++){
            for(int j = 1; j <= n; j++){
                g[i][j] = min(g[i][j], g[i][k]+g[k][j]);
            }
        }
    }
};
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
    while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
struct Edge{
    int to,next,cap,flow;
}edge[maxm];
int tol,head[maxn];
void init()
{
    tol=2;
    memset(head,-1,sizeof(head));
}
void addedge(int u,int v,int w,int rw=0)
{
    edge[tol].to=v;edge[tol].cap=w;edge[tol].flow=0;
    edge[tol].next=head[u];head[u]=tol++;
    edge[tol].to=u;edge[tol].cap=rw;edge[tol].flow=0;
    edge[tol].next=head[v];head[v]=tol++;
}
int Q[maxn];
int dep[maxn],cur[maxn],sta[maxn];
bool bfs(int s,int t,int n)
{
    int front=0,tail=0;
    memset(dep,-1,sizeof(dep[0])*(n+1));
    dep[s]=0;
    Q[tail++]=s;
    while(front<tail){
        int u=Q[front++];
        for(int i=head[u];i!=-1;i=edge[i].next){
            int v=edge[i].to;
            if(edge[i].cap>edge[i].flow&&dep[v]==-1){
                dep[v]=dep[u]+1;
                if(v==t){
                    return true;
                }
                Q[tail++]=v;
            }
        }
    }
    return false;
}
long long dinic(int s,int t,int n)
{
    long long maxflow=0;
    while(bfs(s,t,n)){
        for(int i=0;i<n;i++){
            cur[i]=head[i];
        }
        int u=s,tail=0;
        while(cur[s]!=-1){
            if(u==t){
                int tp=INF;
                for(int i=tail-1;i>=0;i--){
                    tp=min(tp,edge[sta[i]].cap-edge[sta[i]].flow);
                }
                maxflow+=tp;
                for(int i=tail-1;i>=0;i--){
                    edge[sta[i]].flow+=tp;
                    edge[sta[i]^1].flow-=tp;
                    if(edge[sta[i]].cap-edge[sta[i]].flow==0){
                        tail=i;
                    }
                }
                u=edge[sta[tail]^1].to;
            }else if(cur[u]!=-1&&edge[cur[u]].cap>edge[cur[u]].flow&&dep[u]+1==dep[edge[cur[u]].to]){
                sta[tail++]=cur[u];
                u=edge[cur[u]].to;
            }else{
                while(u!=s&&cur[u]==-1){
                    u=edge[sta[--tail]^1].to;
                }
                cur[u]=edge[cur[u]].next;
            }
        }
    }
    return maxflow;
}
//vector<int>fuck[100005];
int fuckacm[100005];
int ps[105];
int in[maxn], out[maxn], shipos[maxn], atk[maxn], f[maxn], p[maxn], baspos[maxn], d[maxn], gold[maxn], val[maxn];
bool svis[maxn];
#define pii pair<int,int>
vector<pii> v1[105];
int main(){
    int n, m, u, v, s, b, k;
    n = read(), m = read();
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n; j++){
            if(i==j) g[i][j] = 0;
            else g[i][j] = g[j][i] = INF;
        }
    }
    for(int i = 1; i <= m; i++){
        u = read(), v = read();
        g[u][v] = g[v][u] = 1;
    }
    floyed(n);
    s = read(), b = read(), k = read();
    for(int i = 1; i <= s; i++){
        shipos[i] = read(), atk[i] = read(), f[i] = read(), p[i] = read();
    }
    for(int i = 1; i <= b; i++){
        baspos[i] = read(), d[i] = read(), gold[i] = read();
        v1[baspos[i]].emplace_back(pii(d[i], gold[i]));
    }
    for(int i = 1; i <= k; i++){
        int tmp1, tmp2;
        tmp1 = read(), tmp2 = read();
        fuckacm[tmp1] = tmp2;
        in[tmp2]++, out[tmp1]++;
    }
    for(int i = 1; i <= n; i++){
        sort(v1[i].begin(), v1[i].end()); ps[i] = 0;
        for(int j = 1; j < v1[i].size(); j++){
            v1[i][j].second = max(v1[i][j].second, v1[i][j-1].second);
        }
    }
    for(int i = 1; i <= s; i++){
        int ma = 0;
        bool flag = false;
        for(int j = 1; j <= n; j++){
            if(g[shipos[i]][j] <= f[i]){
                if(v1[j].empty()) continue;
                while(ps[j] < v1[j].size()-1 && v1[j][ps[j]+1].first <= atk[i]) ps[j]++;
                if(v1[j][ps[j]].first <= atk[i]) ma = max(ma, v1[j][ps[j]].second), flag = true;
            }
        }
        if(!flag) svis[i] = true;
        val[i] = ma-p[i];
    }
    long long ans = 0;
    for(int i = 1; i <= s; i++){
        if(in[i] == 0 && out[i] > 0 && !svis[i]){
            if(val[i] <= 0){
                svis[i] = true;
            }
        }
        if(in[i] == 0 && out[i] == 0 && val[i]>0 && !svis[i]){
            ans += val[i];
            svis[i] = true;
        }
        if(in[i] == 0 && out[i] == 0 && val[i] < 0 && !svis[i]){
            svis[i] = true;
        }
    }
    int S = 2015+1, T = S+1;
    init();
    for(int i = 1; i <= s; i++){
        if(!svis[i]){
            if(val[i] > 0){
                num[i] = ++cnt;
                addedge(S, cnt, val[i]);
                ans += val[i];
            }
            else{
                num[i] = ++cnt;
                addedge(cnt, T, -val[i]);
            }
        }
    }
    for(int i = 1; i <= s; i++){
        if(!svis[i] && val[i] > 0)
            addedge(num[i], num[fuckacm[i]], INF);
    }
    ans -= dinic(S, T, T+1);
    cout << ans;
    return 0;
}

#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <utility>
#include <limits>

struct base_t {
    int64_t position, defense, gold;
    friend std::istream& operator >> (std::istream& flux, base_t& b) {
        flux >> b.position >> b.defense >> b.gold;
        return flux;
    }
    bool operator < (const base_t& b) const {
        //if (this->defense != b.defense)
            return this->defense < b.defense;
        //return this->gold < b.gold;
    }
};

struct ship_t {
    int64_t position, strength, fuel, price;
    friend std::istream& operator >> (std::istream& flux, ship_t& s) {
        flux >> s.position >> s.strength >> s.fuel >> s.price;
        return flux;
    }
};

struct Flow_Edge {
    int from, to;
    int64_t capacity, flow = 0LL;
    Flow_Edge (const int& from, const int& to, const int64_t& capacity): from (from), to (to), capacity (capacity) {
    }
};

constexpr int64_t Inf = 1e12 + 25;
using Ip = std::pair <int64_t, int64_t>;
using Vi = std::vector <int>;
using VVi = std::vector <Vi>;
using Vi64 = std::vector <int64_t>;
using VVi64 = std::vector <Vi64>;
using VIp = std::vector <Ip>;
using VVIp = std::vector <VIp>;
using Vf = std::vector <Flow_Edge>;
using Vs = std::vector <ship_t>;
using Vb = std::vector <base_t>;
using Qi = std::queue <int>;

struct Dinic {
    Vf Edges;
    VVi Adj;
    int n, s, t;
    Vi Level, Ptr;
    Qi Q;
    Dinic (const int& n, const int& s, const int& t): n (n), s (s), t (t) {
        Adj.resize (n), Level.resize (n), Ptr.resize (n);
    }
    void add_edge (const int& u, const int& v, const int64_t& cap) {
        Edges.emplace_back (Flow_Edge (u, v, cap));
        Adj[u].emplace_back (Edges.size () - 1);
        Edges.emplace_back (Flow_Edge (v, u, 0));
        Adj[v].emplace_back (Edges.size () - 1);
    }
    bool bfs () {
        while (!Q.empty ()) {
            int v = Q.front (); Q.pop ();
            for (const auto& id: Adj[v]) {
                if (Edges[id].capacity - Edges[id].flow < 1)
                    continue;
                if (Level[Edges[id].to] != -1)
                    continue;
                Level[Edges[id].to] = Level[v] + 1;
                Q.push (Edges[id].to);
            }
        }
        return Level[t] != -1;
    }
    int64_t dfs (const int& v, const int64_t& pushed) {
        if (!pushed)
            return 0LL;
        if (v == t)
            return pushed;
        for (int& cid = Ptr[v]; cid < (int)Adj[v].size (); ++ cid) {
            int id = Adj[v][cid], u = Edges[id].to;
            if (Level[v] + 1 != Level[u] || Edges[id].capacity - Edges[id].flow < 1)
                continue;
            int64_t transport = dfs (u, Edges[id].capacity - Edges[id].flow);
            if (!transport)
                continue;
            Edges[id].flow += transport;
            Edges[id ^ 1].flow -= transport;
            return transport;
        }
        return 0LL;
    }
    int64_t max_flow () {
        int64_t f = 0LL;
        while (true) {
            std::fill (Level.begin (), Level.end (), -1);
            Level[s] = 0;
            Q.push (s);
            if (!bfs ())
                break;
            std::fill (Ptr.begin (), Ptr.end (), 0);
            while (int64_t pushed = dfs (s, Inf))
                f += pushed;
        }
        return f;
    }
};

int n, m, u, v, s, b, k;
Vi64 Value;
VVi64 Cost;
Vs Ships;
Vb Bases;
VVIp Bases_at;

int main () {
    std::cin >> n >> m;
    Cost.assign (n + 1, Vi64 (n + 1, Inf));
    for (int i = 1; i <= m; ++ i)
        std::cin >> u >> v, Cost[u][v] = Cost[v][u] = std::min (Cost[u][v], 1LL);

    for (int k = 1; k <= n; ++ k)
        for (int i = 1; i <= n; ++ i)
            for (int j = 1; j <= n; ++ j)
                Cost[i][j] = std::min (Cost[i][j], Cost[i][k] + Cost[k][j]);

    std::cin >> s >> b >> k;
    Value.resize (s + 1), Bases_at.resize (n + 1);
    Ships.resize (s + 1), Bases.resize (b + 1);
    for (int i = 1; i <= s; ++ i)
        std::cin >> Ships[i];
    for (int i = 1; i <= b; ++ i)
        std::cin >> Bases[i];

    std::sort (Bases.begin () + 1, Bases.end ());
    for (int i = 1; i <= b; ++ i) {
        int pos = Bases[i].position;
        if (Bases_at[pos].empty () || Bases_at[pos].back ().second < Bases[i].gold)
            Bases_at[pos].emplace_back (std::make_pair (Bases[i].defense, Bases[i].gold));
    }

    Dinic dinic (s + 2, 0, s + 1);
    int source = 0, sink = s + 1;
    int64_t ans = 0LL;
    for (int i = 1; i <= s; ++ i) {
        bool found = false;
        for (int p = 1; p <= n; ++ p) {
            if (Cost[Ships[i].position][p] > Ships[i].fuel)
                continue;
            auto it = std::upper_bound (Bases_at[p].begin (), Bases_at[p].end (), std::make_pair (Ships[i].strength, Inf));
            if (it != Bases_at[p].begin ())
                -- it, found = true, Value[i] = std::max (Value[i], it->second);
        }
        Value[i] -= Ships[i].price;
        if (!found)
            Value[i] = -Inf;
        if (Value[i] >= 0)
            ans += Value[i], dinic.add_edge (source, i, Value[i]);
        else
            dinic.add_edge (i, sink, -Value[i]);
    }

    for (int i = 1; i <= k; ++ i)
        std::cin >> u >> v,
        dinic.add_edge (u, v, Inf);

    std::cout << ans - dinic.max_flow ();

    return 0;
}

//Author: Heltion
//Date: 07-31-2019
#include<bits/stdc++.h>
using namespace std;
using LL = long long;
template<typename T>void no(T s){cout << s; exit(0);}
void no(){cout << "NO"; exit(0);}
constexpr LL maxm = 120;
constexpr LL maxn = 120000;
LL d[maxm][maxm];
LL sx[maxn], a[maxn], f[maxn], p[maxn], bx[maxn], dd[maxn], g[maxn];
struct FlowEdge {
    int v, u;
    long long cap, flow = 0;
    FlowEdge(int v, int u, long long cap) : v(v), u(u), cap(cap) {}
};

struct Dinic {
    const long long flow_inf = 1e18;
    vector<FlowEdge> edges;
    vector<vector<int>> adj;
    int n, m = 0;
    int s, t;
    vector<int> level, ptr;
    queue<int> q;

    Dinic(int n, int s, int t) : n(n), s(s), t(t) {
        adj.resize(n);
        level.resize(n);
        ptr.resize(n);
    }

    void add_edge(int v, int u, long long cap) {
        edges.emplace_back(v, u, cap);
        edges.emplace_back(u, v, 0);
        adj[v].push_back(m);
        adj[u].push_back(m + 1);
        m += 2;
    }

    bool bfs() {
        while (!q.empty()) {
            int v = q.front();
            q.pop();
            for (int id : adj[v]) {
                if (edges[id].cap - edges[id].flow < 1)
                    continue;
                if (level[edges[id].u] != -1)
                    continue;
                level[edges[id].u] = level[v] + 1;
                q.push(edges[id].u);
            }
        }
        return level[t] != -1;
    }

    long long dfs(int v, long long pushed) {
        if (pushed == 0)
            return 0;
        if (v == t)
            return pushed;
        for (int& cid = ptr[v]; cid < (int)adj[v].size(); cid++) {
            int id = adj[v][cid];
            int u = edges[id].u;
            if (level[v] + 1 != level[u] || edges[id].cap - edges[id].flow < 1)
                continue;
            long long tr = dfs(u, min(pushed, edges[id].cap - edges[id].flow));
            if (tr == 0)
                continue;
            edges[id].flow += tr;
            edges[id ^ 1].flow -= tr;
            return tr;
        }
        return 0;
    }

    long long flow() {
        long long f = 0;
        while (true) {
            fill(level.begin(), level.end(), -1);
            level[s] = 0;
            q.push(s);
            if (!bfs())
                break;
            fill(ptr.begin(), ptr.end(), 0);
            while (long long pushed = dfs(s, flow_inf)) {
                f += pushed;
            }
        }
        return f;
    }
};
bool vis[maxn];
vector<pair<LL, LL>> v[maxn];
int main(){
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	cout.tie(nullptr);
	cout << fixed << setprecision(20);
	LL n, m;
	cin >> n >> m;
	for(LL i = 1; i <= n; i += 1)
		for(LL j = 1; j <= n; j += 1) if(i != j) d[i][j] = 1e9;
	for(LL i = 1; i <= m; i += 1){
		LL u, v;
		cin >> u >> v;
		if(u != v) d[u][v] = d[v][u] = 1;
	}
	for(LL k = 1; k <= n; k += 1)
		for(LL i = 1; i <= n; i += 1)
			for(LL j = 1; j <= n; j += 1)
				d[i][j] = min(d[i][j], d[i][k] + d[j][k]);
	LL s, b, k;
	cin >> s >> b >> k;
	LL ans = 0;
	for(LL i = 1; i <= s; i += 1)
		cin >> sx[i] >> a[i] >> f[i] >> p[i];
	for(LL i = 1; i <= b; i += 1)
		cin >> bx[i] >> dd[i] >> g[i];

	Dinic dinic(2 * s + 2, 0, 2 * s + 1);
	for(LL i = 1; i <= k; i += 1){
		int u, v;
		cin >> u >> v;
		dinic.add_edge(u, 2 * v, 1e18);
		vis[u] = vis[v] = true;
	}
	for(LL j = 1; j <= b; j += 1)
		v[bx[j]].push_back(make_pair(dd[j], g[j]));
	for(LL j = 1; j <= n; j += 1){
		sort(v[j].begin(), v[j].end());
		for(LL i = 1; i < (LL)v[j].size(); i += 1)
			v[j][i].second = max(v[j][i].second, v[j][i - 1].second);
	}
	for(LL i = 1; i <= s; i += 1){
		LL x = -1e15;
		for(LL j = 1; j <= n; j += 1)
			if(d[sx[i]][j] <= f[i]) {
				auto p = upper_bound(v[j].begin(), v[j].end(), make_pair(a[i], (LL)1e18));
				if(p == v[j].begin()) continue;
				p --;
				x = max(x, p->second);
			}
		if(vis[i]){
			dinic.add_edge(i, 2 * s + 1, p[i]);
			if(x > 0){
				ans += x;
				dinic.add_edge(0, 2 * i, x);
			}
			else dinic.add_edge(2 * i, 2 * s + 1, -x);
			dinic.add_edge(2 * i, i, 1e18);
		}
		else ans += max(0LL, x - p[i]);
	}
	cout << ans - dinic.flow();
	return 0;
}

#include <bits/stdc++.h>
//
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 100015;
const int maxm = 1000005;
int g[105][105];
int num[maxn];
int id[maxn];
int cnt;
void floyed(int n){
    for(int k = 1; k <= n; k++){
        for(int i = 1; i <= n; i++){
            for(int j = 1; j <= n; j++){
                g[i][j] = min(g[i][j], g[i][k]+g[k][j]);
            }
        }
    }
};
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
    while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
struct Edge{
    int to,next,cap,flow;
}edge[maxm];
int tol,head[maxn];
void init()
{
    tol=2;
    memset(head,-1,sizeof(head));
}
void addedge(int u,int v,int w,int rw=0)
{
    edge[tol].to=v;edge[tol].cap=w;edge[tol].flow=0;
    edge[tol].next=head[u];head[u]=tol++;
    edge[tol].to=u;edge[tol].cap=rw;edge[tol].flow=0;
    edge[tol].next=head[v];head[v]=tol++;
}
int Q[maxn];
int dep[maxn],cur[maxn],sta[maxn];
bool bfs(int s,int t,int n)
{
    int front=0,tail=0;
    memset(dep,-1,sizeof(dep[0])*(n+1));
    dep[s]=0;
    Q[tail++]=s;
    while(front<tail){
        int u=Q[front++];
        for(int i=head[u];i!=-1;i=edge[i].next){
            int v=edge[i].to;
            if(edge[i].cap>edge[i].flow&&dep[v]==-1){
                dep[v]=dep[u]+1;
                if(v==t){
                    return true;
                }
                Q[tail++]=v;
            }
        }
    }
    return false;
}
long long dinic(int s,int t,int n)
{
    long long maxflow=0;
    while(bfs(s,t,n)){
        for(int i=0;i<n;i++){
            cur[i]=head[i];
        }
        int u=s,tail=0;
        while(cur[s]!=-1){
            if(u==t){
                int tp=INF;
                for(int i=tail-1;i>=0;i--){
                    tp=min(tp,edge[sta[i]].cap-edge[sta[i]].flow);
                }
                maxflow+=tp;
                for(int i=tail-1;i>=0;i--){
                    edge[sta[i]].flow+=tp;
                    edge[sta[i]^1].flow-=tp;
                    if(edge[sta[i]].cap-edge[sta[i]].flow==0){
                        tail=i;
                    }
                }
                u=edge[sta[tail]^1].to;
            }else if(cur[u]!=-1&&edge[cur[u]].cap>edge[cur[u]].flow&&dep[u]+1==dep[edge[cur[u]].to]){
                sta[tail++]=cur[u];
                u=edge[cur[u]].to;
            }else{
                while(u!=s&&cur[u]==-1){
                    u=edge[sta[--tail]^1].to;
                }
                cur[u]=edge[cur[u]].next;
            }
        }
    }
    return maxflow;
}
//vector<int>fuck[100005];
int fuckacm[100005];
int ps[105];
int in[maxn], out[maxn], shipos[maxn], atk[maxn], f[maxn], p[maxn], baspos[maxn], d[maxn], gold[maxn], val[maxn];
bool svis[maxn];
#define pii pair<int,int>
vector<pii> v1[105];
bool cmp(int x, int y){
    return atk[x] < atk[y];
}
int main(){
    int n, m, u, v, s, b, k;
    n = read(), m = read();
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n; j++){
            if(i==j) g[i][j] = 0;
            else g[i][j] = g[j][i] = INF;
        }
    }
    for(int i = 1; i <= m; i++){
        u = read(), v = read();
        g[u][v] = g[v][u] = 1;
    }
    floyed(n);
    s = read(), b = read(), k = read();
    for(int i = 1; i <= s; i++){
        shipos[i] = read(), atk[i] = read(), f[i] = read(), p[i] = read();
        id[i] = i;
    }
    sort(id+1, id+1+s, cmp);
    for(int i = 1; i <= b; i++){
        baspos[i] = read(), d[i] = read(), gold[i] = read();
        v1[baspos[i]].emplace_back(pii(d[i], gold[i]));
    }
    for(int i = 1; i <= k; i++){
        int tmp1, tmp2;
        tmp1 = read(), tmp2 = read();
        fuckacm[tmp1] = tmp2;
        in[tmp2]++, out[tmp1]++;
    }
    for(int i = 1; i <= n; i++){
        sort(v1[i].begin(), v1[i].end()); ps[i] = 0;
        for(int j = 1; j < v1[i].size(); j++){
            v1[i][j].second = max(v1[i][j].second, v1[i][j-1].second);
        }
    }
    for(int I = 1; I <= s; I++){
        int i = id[I];
        int ma = 0;
        bool flag = false;
        for(int j = 1; j <= n; j++){
            if(g[shipos[i]][j] <= f[i]){
                if(v1[j].empty()) continue;
                while(ps[j] < v1[j].size()-1 && v1[j][ps[j]+1].first <= atk[i]) ps[j]++;
                if(v1[j][ps[j]].first <= atk[i]) ma = max(ma, v1[j][ps[j]].second), flag = true;
            }
        }
        if(!flag) svis[i] = true;
        val[i] = ma-p[i];
    }
    long long ans = 0;
    for(int i = 1; i <= s; i++){
        if(in[i] == 0 && out[i] > 0 && !svis[i]){
            if(val[i] <= 0){
                svis[i] = true;
            }
        }
        if(in[i] == 0 && out[i] == 0 && val[i]>0 && !svis[i]){
            ans += val[i];
            svis[i] = true;
        }
        if(in[i] == 0 && out[i] == 0 && val[i] < 0 && !svis[i]){
            svis[i] = true;
        }
    }
    int S = 2015+1, T = S+1;
    init();
    for(int i = 1; i <= s; i++){
        if(!svis[i]){
            if(val[i] > 0){
                num[i] = ++cnt;
                addedge(S, cnt, val[i]);
                ans += val[i];
            }
            else{
                num[i] = ++cnt;
                addedge(cnt, T, -val[i]);
            }
        }
    }
    for(int i = 1; i <= s; i++){
        if(!svis[i] && val[i] > 0)
            addedge(num[i], num[fuckacm[i]], INF);
    }
    ans -= dinic(S, T, T+1);
    cout << ans;
    return 0;
}

#include<bits/stdc++.h>

using namespace std;

#define double long double

typedef pair<int,int> ii;
typedef pair<int,long long> il;
typedef pair<long long,long long> ll;
typedef pair<ll,int> lli;
typedef pair<long long,int> li;
typedef pair<double,double> dd;
typedef pair<ii,int> iii;
typedef pair<double,int> di;
typedef pair<int,ii> iii2;
typedef pair<ii,ii> iiii;
typedef vector<int> vi;
long long mod = 1000000007LL;
long long large = 2000000000000000000LL;

struct Edge {
	int from,to;
	long long cap,flow;
};

struct Dinic {
	int n,m,s,t;
	vector<Edge> edges;
	vector<vector<int> > G;
	vector<bool> vis;
	vector<int> dis;
	vector<int> cur;
	void init(int maxn){
		edges.clear();
		G.assign(maxn+10,vector<int>(0));
		vis.assign(maxn+10,false);
		dis.assign(maxn+10,0);
		cur.assign(maxn+10,0);
		n=maxn;
	}
	void addEdge(int from,int to,long long cap){
		edges.push_back((Edge){from,to,cap,0});
		edges.push_back((Edge){to,from,0,0});
		m=edges.size();
		G[from].push_back(m-2);
		G[to].push_back(m-1);
	}
	bool BFS() {
		vis.assign(n+10,false);
		queue<int> q;
		q.push(s);
		dis[s]=0;
		vis[s]=true;
		while(!q.empty()){
			int u=q.front();
			q.pop();
			for(int i=0;i<(int)G[u].size();i++){
				Edge& e=edges[G[u][i]];
				if(!vis[e.to]&&e.cap>e.flow){
					vis[e.to]=1;
					dis[e.to]=dis[u]+1;
					q.push(e.to);
				}
			}
		}
		return vis[t];
	}
	long long DFS(int x,long long a){
		if(x==t||a==0) return a;
		long long flow=0,f;
		for(int& i=cur[x];i<(int)G[x].size();i++){
			Edge& e=edges[G[x][i]];
			if(dis[x]+1==dis[e.to]&&(f=DFS(e.to,min(a,e.cap-e.flow)))>0){
				e.flow+=f;
				edges[G[x][i]^1].flow-=f;
				flow+=f;
				a-=f;
				if(a==0) break;
			}
		}
		return flow;
	}
	long long maxflow(int s,int t){
		this->s=s;
		this->t=t;
		long long flow=0;
		while(BFS()){
			cur.assign(n+10,0);
			flow+=DFS(s,1000000000);
		}
		return flow;
	}
	void clearflow(){
		vis.assign(n+10,false);
		dis.assign(n+10,0);
		cur.assign(n+10,0);
		for(int i=0;i<(int)edges.size();i++){
			edges[i].flow=0;
		}
	}
};

int main(){

	int n,m;
	cin>>n>>m;
	vector<vector<int> > g(n,vector<int>(n,1000000000));
	for(int i=0;i<m;i++){
		int x,y;
		cin>>x>>y;
		x--;y--;
		g[x][y] = g[y][x] =1;
	}

	for(int i=0;i<n;i++) g[i][i] = 0;
	for(int k=0;k<n;k++) for(int i=0;i<n;i++) for(int j=0;j<n;j++) g[i][j] = min(g[i][j],g[i][k]+g[k][j]);

	int s,b;
	cin>>s>>b;

	int k;
	cin>>k;

	vector<int> ps(s,0),a(s,0),f(s,0),p(s,0);
	vector<int> pb(b,0),d(b,0),gold(b,0);
	for(int i=0;i<s;i++){
		cin>>ps[i]>>a[i]>>f[i]>>p[i];
		ps[i]--;
	}
	for(int i=0;i<b;i++){
		cin>>pb[i]>>d[i]>>gold[i];
		pb[i]--;
	}

	vector<vector<ii> > adj(n);
	for(int i=0;i<b;i++){
		adj[pb[i]].push_back(ii(d[i],gold[i]));
	}
	for(int i=0;i<n;i++) sort(adj[i].begin(),adj[i].end());
	for(int i=0;i<n;i++){
		for(int j=0;j<(int)adj[i].size();j++){
			if(j) adj[i][j].second = max(adj[i][j].second,adj[i][j-1].second);
		}
	}

	for(int i=0;i<s;i++){
		int ans = 0;
		for(int j=0;j<n;j++){
			if(g[ps[i]][j]>f[i]) continue;
			int pt = upper_bound(adj[j].begin(),adj[j].end(),ii(a[i],1000000010))-adj[j].begin();
			pt--;
			if(pt>=0) ans = max(ans,adj[j][pt].second);
		}
		p[i] = ans-p[i];
	}

	Dinic din;
	din.init(s+10);
	int st = s;
	int en = st+1;
	long long sum = 0;
	for(int i=0;i<s;i++){
		if(p[i]>=0){
			din.addEdge(st,i,p[i]);
			sum+=p[i];
		}else din.addEdge(i,en,-p[i]);
	}

	for(int i=0;i<k;i++){
		int x,y;
		cin>>x>>y;
		x--;y--;
		din.addEdge(x,y,large);
	}

	cout<<sum-din.maxflow(st,en)<<endl;

    return 0;
}

#include <bits/stdc++.h>

#define fast_cin() ios_base::sync_with_stdio(false); cin.tie(0);
#define pb push_back

using namespace std;

typedef long double ld;
typedef long long ll;
typedef long long LL;
typedef pair <int, int> pii;
typedef pair <ll, ll> pll;

struct Edge {
  int u, v;
  LL cap, flow;
  Edge() {}
  Edge(int u, int v, LL cap): u(u), v(v), cap(cap), flow(0) {}
};

struct Dinic {
  int N;
  vector<Edge> E;
  vector<vector<int>> g;
  vector<int> d, pt;

  Dinic(int N): N(N), E(0), g(N), d(N), pt(N) {}

  void AddEdge(int u, int v, LL cap) {
    if (u != v) {
      E.emplace_back(Edge(u, v, cap));
      g[u].emplace_back(E.size() - 1);
      E.emplace_back(Edge(v, u, 0));
      g[v].emplace_back(E.size() - 1);
    }
  }

  bool BFS(int S, int T) {
    queue<int> q({S});
    fill(d.begin(), d.end(), N + 1);
    d[S] = 0;
    while(!q.empty()) {
      int u = q.front(); q.pop();
      if (u == T) break;
      for (int k: g[u]) {
        Edge &e = E[k];
        if (e.flow < e.cap && d[e.v] > d[e.u] + 1) {
          d[e.v] = d[e.u] + 1;
          q.emplace(e.v);
        }
      }
    }
    return d[T] != N + 1;
  }

  LL DFS(int u, int T, LL flow = -1) {
    if (u == T || flow == 0) return flow;
    for (int &i = pt[u]; i < g[u].size(); ++i) {
      Edge &e = E[g[u][i]];
      Edge &oe = E[g[u][i]^1];
      if (d[e.v] == d[e.u] + 1) {
        LL amt = e.cap - e.flow;
        if (flow != -1 && amt > flow) amt = flow;
        if (LL pushed = DFS(e.v, T, amt)) {
          e.flow += pushed;
          oe.flow -= pushed;
          return pushed;
        }
      }
    }
    return 0;
  }

  LL MaxFlow(int S, int T) {
    LL total = 0;
    while (BFS(S, T)) {
      fill(pt.begin(), pt.end(), 0);
      while (LL flow = DFS(S, T))
        total += flow;
    }
    return total;
  }
};

struct ship_t {
	ll x, a, f, p;
};

struct base_t {
	ll x, d, g;
	bool operator<(const base_t &o) const {
		return d < o.d;
	}
};

const int N = 1e2 + 10, S = 1e5 + 10;
const ll inf = 1e12 + 42;

ship_t ship[S];
base_t base[S];
ll g[N][N];
vector<int> dep[S];
vector<pll> bases_at[N];
bool seen[S];
ll val[S];

int main()
{
	fast_cin();
	int n, m;
	cin >> n >> m;
	for (int i = 1; i <= n; ++i) {
		for (int j = i + 1; j <= n; ++j) {
			g[i][j] = g[j][i] = inf;
		}
	}
	for (int i = 0; i < m; ++i) {
		int u, v;
		cin >> u >> v;
		g[u][v] = g[v][u] = min(g[u][v], 1ll);
	}
	for (int k = 1; k <= n; ++k) {
		for (int i = 1; i <= n; ++i) {
			for (int j = 1; j <= n; ++j) {
				g[i][j] = min(g[i][j], g[i][k] + g[k][j]);
			}
		}
	}
	int s, b, k;
	cin >> s >> b >> k;
	for (int i = 1; i <= s; ++i) {
		cin >> ship[i].x >> ship[i].a >> ship[i].f >> ship[i].p;
	}
	for (int i = 1; i <= b; ++i) {
		cin >> base[i].x >> base[i].d >> base[i].g;
	}
	sort(base + 1, base + 1 + b);
	for (int i = 1; i <= b; ++i) {
		int p = base[i].x;
		if (bases_at[p].empty() or bases_at[p].back().second < base[i].g) {
			bases_at[p].pb({base[i].d, base[i].g});
		}
	}
	Dinic dinic(s + 2);
	int source = 0, sink = s + 1;
	ll ans = 0;
	for (int i = 1; i <= s; ++i) {
		for (int p = 1; p <= n; ++p) {
			if (g[ship[i].x][p] > ship[i].f) {
				continue;
			}
			auto it = upper_bound(bases_at[p].begin(), bases_at[p].end(), make_pair(ship[i].a, inf));
			if (it != bases_at[p].begin()) {
				--it;
				val[i] = max(val[i], it->second);
			}
		}
		val[i] -= ship[i].p;
		if (val[i] >= 0) {
			ans += val[i];
			dinic.AddEdge(source, i, val[i]);
		} else {
			dinic.AddEdge(i, sink, -val[i]);
		}
	}
	for (int i = 1; i <= k; ++i) {
		int u, v;
		cin >> u >> v;
		dep[u].pb(v);
	}
	for (int i = 1; i <= s; ++i) {
		if (val[i] < 0) {
			continue;
		}
		vector<int> vis = {i};
		queue<int> q;
		q.push(i);
		seen[i] = true;
		while (!q.empty()) {
			int u = q.front();
			q.pop();
			if (val[u] < 0) {
				dinic.AddEdge(i, u, inf);
			}
			for (auto &v : dep[u]) {
				if (!seen[v]) {
					seen[v] = true;
					vis.pb(v);
					q.push(v);
				}
			}
		}
		for (auto &u : vis) {
			seen[u] = false;
		}
	}
	cout << ans - dinic.MaxFlow(source, sink);
}

#include <iostream>
#include <fstream>
#include <numeric>
#include <iomanip>
#include <cstring>
#include <string>
#include <algorithm>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <deque>

#define sz(a) (int)((a).size())
#define all(a) (a).begin(), (a).end()
#define pb push_back

using namespace std; using ll = long long; using vi = vector<int>; using pii = pair<int, int>; using ld = long double;

const int inf = (int)1e9 + 100;

int n, m;
int d[100][100];
int s, b, k;

struct ship {
	int x, a, f, p;
} ss[100000];

struct base {
	int x, d, g;
} bb[100000];

struct maxflow {
	struct edge {
		int to, c, f;
	};

	vector<edge> e;
	vector<vi> g;
	int N, S, T;
	vi pt, d;
	int A;

	bool bfs() {
		fill_n(d.begin(), N, inf);
		d[S] = 0;
		queue<int> q;
		q.push(S);
		while (!q.empty()) {
			int v = q.front();
			q.pop();
			for (int i : g[v]) {
				edge& ee = e[i];
				if (ee.c - ee.f >= A && d[ee.to] == inf) {
					d[ee.to] = d[v] + 1;
					q.push(ee.to);
				}
			}

		}
		return (d[T] != inf);
	}

	int dfs(int v, int cmin) {
		if (v == T) {
			return cmin;
		}
		for (; pt[v] < sz(g[v]); pt[v]++) {
			int i = g[v][pt[v]];
			edge& ee = e[i];
			if (ee.c - ee.f >= A && d[ee.to] == d[v] + 1) {
				int f = dfs(ee.to, min(cmin, ee.c - ee.f));
				if (f > 0) {
					ee.f += f;
					e[i ^ 1].f -= f;
					return f;
				}
			}
		}
		return 0;
	}

	void dinic() {
		d.resize(N);
		pt.resize(N);
		int mf = 0;
		for (A = inf; A; A >>= 1) {
			while (bfs()) {
				fill_n(pt.begin(), N, 0);
				while (dfs(S, inf));
			}
		}
	}

	void addEdge(int u, int v, int c) {
		static int i = 0;
		e.pb({ v, c, 0 });
		e.pb({ u, 0, 0 });
		g[u].pb(i);
		g[v].pb(i ^ 1);
		i += 2;
	}

	void zhfs(int v, vector<bool>& was) {
		was[v] = true;
		for (int i : g[v]) {
			edge& ee = e[i];
			if (ee.c - ee.f > 0 && !was[ee.to]) {
				zhfs(ee.to, was);
			}
		}
	}
};

vi g1[100000];
vector<pii> e;
bool ban[100000];
int w[100000];

void dfs(int v) {
	ban[v] = true;
	for (int to : g1[v]) if(!ban[to]) dfs(to);
}

vector<pii> pl[100];
vi pm[100];

int32_t main() {
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	//ifstream cin("in.txt");
	cin >> n >> m;
	for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) if(i != j) d[i][j] = inf;
	for (int i = 0; i < m; i++) {
		int u, v; cin >> u >> v; --u; --v; d[u][v] = d[v][u] = 1;
	}
	for (int k = 0; k < n; k++) for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
	cin >> s >> b >> k;
	for (int i = 0; i < s; i++) cin >> ss[i].x >> ss[i].a >> ss[i].f >> ss[i].p, --ss[i].x;
	for (int i = 0; i < b; i++) cin >> bb[i].x >> bb[i].d >> bb[i].g, --bb[i].x, pl[bb[i].x].pb({ bb[i].d, bb[i].g });
	for (int i = 0; i < n; i++) {
		if (pl[i].empty()) continue;
		sort(all(pl[i]));
		pm[i].resize(sz(pl[i]));
		pm[i][0] = pl[i][0].second;
		for (int j = 1; j < sz(pm[i]); j++) {
			pm[i][j] = max(pm[i][j - 1], pl[i][j].second);
		}
	}
	vi broken;
	maxflow grape;
	grape.N = s + 2;
	grape.S = grape.N - 2;
	grape.T = grape.N - 1;
	grape.g.resize(grape.N);
	vi ord(s); iota(all(ord), 0);
	sort(all(ord), [](int i, int j) { return ss[i].a < ss[j].a; });
	vi pt(n, -1);
	for (int i : ord) {
		int hi = -1;
		//for (int p = 0; p < n; p++) if (ss[i].f >= d[ss[i].x][p]) for (pii bas : pl[p]) if (ss[i].a >= bas.first) hi = max(hi, bas.second);
		// me for (int p = 0; p < n; p++) if (ss[i].f >= d[ss[i].x][p]) for (int t = 0; t < sz(pl[p]) && ss[i].a >= pl[p][t].first; t++) hi = max(hi, pm[p][t]);
 		//for (int j = 0; j < b; j++) if (ss[i].a >= bb[j].d && ss[i].f >= d[ss[i].x][bb[j].x]) hi = max(hi, bb[j].g);
		for (int p = 0; p < n; p++) if(ss[i].f >= d[ss[i].x][p]) {
			while (pt[p] + 1 < sz(pl[p]) && ss[i].a >= pl[p][pt[p] + 1].first) pt[p]++;
			if (pt[p] != -1) hi = max(hi, pm[p][pt[p]]);
		}
		if (hi == -1) broken.pb(i);
		else {
			hi -= ss[i].p;
			if (hi < 0) grape.addEdge(i, grape.T, -hi);
			else if (hi > 0) grape.addEdge(grape.S, i, hi);
			w[i] = hi;
			cout << i << ' ' << w[i] << endl;
		}
	}
	for (int i = 0; i < k; i++) {
		int u, v; cin >> u >> v; --u; --v;
		g1[v].pb(u); e.pb({ u, v });
	}
	for (int u : broken) if (!ban[u]) dfs(u);
	for (pii r : e) {
		int u = r.first, v = r.second;
		if (!ban[u] && !ban[v]) grape.addEdge(u, v, inf);
	}
	grape.dinic();
	vector<bool> was(grape.N, false);
	grape.zhfs(grape.S, was);
	ll ans = 0;
	for (int u = 0; u < s; u++) {
		if (was[u]) {
			ans += w[u];
		}
	}
	cout << ans;
}

#include <bits/stdc++.h>
//
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 100015;
const int maxm = 1000005;
int g[105][105];
int num[maxn];
int cnt;
void floyed(int n){
    for(int k = 1; k <= n; k++){
        for(int i = 1; i <= n; i++){
            for(int j = 1; j <= n; j++){
                g[i][j] = min(g[i][j], g[i][k]+g[k][j]);
            }
        }
    }
};
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
    while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
struct Edge{
    int to,next,cap,flow;
}edge[maxm];
int tol,head[maxn];
void init()
{
    tol=2;
    memset(head,-1,sizeof(head));
}
void addedge(int u,int v,int w,int rw=0)
{
    edge[tol].to=v;edge[tol].cap=w;edge[tol].flow=0;
    edge[tol].next=head[u];head[u]=tol++;
    edge[tol].to=u;edge[tol].cap=rw;edge[tol].flow=0;
    edge[tol].next=head[v];head[v]=tol++;
}
int Q[maxn];
int dep[maxn],cur[maxn],sta[maxn];
bool bfs(int s,int t,int n)
{
    int front=0,tail=0;
    memset(dep,-1,sizeof(dep[0])*(n+1));
    dep[s]=0;
    Q[tail++]=s;
    while(front<tail){
        int u=Q[front++];
        for(int i=head[u];i!=-1;i=edge[i].next){
            int v=edge[i].to;
            if(edge[i].cap>edge[i].flow&&dep[v]==-1){
                dep[v]=dep[u]+1;
                if(v==t){
                    return true;
                }
                Q[tail++]=v;
            }
        }
    }
    return false;
}
long long dinic(int s,int t,int n)
{
    long long maxflow=0;
    while(bfs(s,t,n)){
        for(int i=0;i<n;i++){
            cur[i]=head[i];
        }
        int u=s,tail=0;
        while(cur[s]!=-1){
            if(u==t){
                int tp=INF;
                for(int i=tail-1;i>=0;i--){
                    tp=min(tp,edge[sta[i]].cap-edge[sta[i]].flow);
                }
                maxflow+=tp;
                for(int i=tail-1;i>=0;i--){
                    edge[sta[i]].flow+=tp;
                    edge[sta[i]^1].flow-=tp;
                    if(edge[sta[i]].cap-edge[sta[i]].flow==0){
                        tail=i;
                    }
                }
                u=edge[sta[tail]^1].to;
            }else if(cur[u]!=-1&&edge[cur[u]].cap>edge[cur[u]].flow&&dep[u]+1==dep[edge[cur[u]].to]){
                sta[tail++]=cur[u];
                u=edge[cur[u]].to;
            }else{
                while(u!=s&&cur[u]==-1){
                    u=edge[sta[--tail]^1].to;
                }
                cur[u]=edge[cur[u]].next;
            }
        }
    }
    return maxflow;
}
//vector<int>fuck[100005];
int fuckacm[100005];
int ps[105];
int in[maxn], out[maxn], shipos[maxn], atk[maxn], f[maxn], p[maxn], baspos[maxn], d[maxn], gold[maxn], val[maxn];
bool svis[maxn];
#define pii pair<int,int>
vector<pii> v1[105];
int main(){
    int n, m, u, v, s, b, k;
    n = read(), m = read();
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n; j++){
            if(i==j) g[i][j] = 0;
            else g[i][j] = g[j][i] = INF;
        }
    }
    for(int i = 1; i <= m; i++){
        u = read(), v = read();
        g[u][v] = g[v][u] = 1;
    }
    floyed(n);
    s = read(), b = read(), k = read();
    for(int i = 1; i <= s; i++){
        shipos[i] = read(), atk[i] = read(), f[i] = read(), p[i] = read();
    }
    for(int i = 1; i <= b; i++){
        baspos[i] = read(), d[i] = read(), gold[i] = read();
        v1[baspos[i]].emplace_back(pii(d[i], gold[i]));
    }
    for(int i = 1; i <= k; i++){
        int tmp1, tmp2;
        tmp1 = read(), tmp2 = read();
        fuckacm[tmp1] = tmp2;
        in[tmp2]++, out[tmp1]++;
    }
    for(int i = 1; i <= n; i++){
        sort(v1[i].begin(), v1[i].end()); ps[i] = 0;
        for(int j = 1; j < v1[i].size(); j++){
            v1[i][j].second = max(v1[i][j].second, v1[i][j-1].second);
        }
    }
    for(int i = 1; i <= s; i++){
        int ma = -INF;
        for(int j = 1; j <= n; j++){
            if(g[shipos[i]][j] <= f[i]){
                if(v1[j].empty()) continue;
                while(ps[j] < v1[j].size()-1 && v1[j][ps[j]+1].first <= atk[i]) ps[j]++;
                if(v1[j][ps[j]].first <= atk[i]) ma = max(ma, v1[j][ps[j]].second);
            }
        }
        val[i] = 0-p[i];
    }
    long long ans = 0;
    for(int i = 1; i <= s; i++){
        if(in[i] == 0 && out[i] > 0 && !svis[i]){
            if(val[i] <= 0){
                svis[i] = true;
            }
        }
        if(in[i] == 0 && out[i] == 0 && val[i]>0 && !svis[i]){
            ans += val[i];
            svis[i] = true;
        }
        if(in[i] == 0 && out[i] == 0 && val[i] < 0 && !svis[i]){
            svis[i] = true;
        }
    }
    int S = 2015+1, T = S+1;
    init();
    for(int i = 1; i <= s; i++){
        if(!svis[i]){
            if(val[i] > 0){
                num[i] = ++cnt;
                addedge(S, cnt, val[i]);
                ans += val[i];
            }
            else{
                num[i] = ++cnt;
                addedge(cnt, T, -val[i]);
            }
        }
    }
    for(int i = 1; i <= s; i++){
        if(!svis[i] && val[i] > 0)
            addedge(num[i], num[fuckacm[i]], INF);
    }
    ans -= dinic(S, T, T+1);
    cout << ans;
    return 0;
}

#include<bits/stdc++.h>
using namespace std;

const int MAXN=3000+5,MAXM=10000+10;
const long long int INF = 1e15;
bool visit[MAXN];
int head[MAXN],dist[MAXN],stamp,tmphead[MAXN];
struct EDGE{
   int to;
   long long int r;
   int next;
}edge[MAXM*2];
void init(){
   stamp=0;
   memset(head,-1,sizeof head);
}
void addedge(int a,int b,long long int c){
   edge[stamp]={b,c,head[a]};
   head[a]=stamp++;
   edge[stamp]={a,0,head[b]};
   head[b]=stamp++;
}
int BFS(int s,int t){
   for(int i=0;i<=t;i++)//The nodes being used
      dist[i]=1e9;
   memset(visit,0,sizeof visit);
   queue<int> q;
   q.push(s);dist[s]=0;visit[s]=true;
   while(!q.empty()){
      int now=q.front();q.pop();
      for(int i=head[now];i!=-1;i=edge[i].next){
         int nextnode=edge[i].to;
         if(edge[i].r>0&&!visit[nextnode]){
            dist[nextnode]=dist[now]+1;
            visit[nextnode]=true;
            q.push(nextnode);
            if(nextnode==t)   return dist[t];
         }
      }
   }
   return -1;
}
long long int DFS(int now,long long int df,int t){
   if(now==t)  return df;
   visit[now]=true;
   for(int i=tmphead[now];i!=-1;tmphead[now]=i=edge[i].next){
      int nextnode=edge[i].to;
      if(edge[i].r>0&&dist[now]+1==dist[nextnode]&&!visit[nextnode]){
         long long int f=DFS(nextnode,min(df,edge[i].r),t);
         if(f){
            edge[i].r-=f;
            edge[i^1].r+=f;
            return f;
         }
      }
   }
   return 0;
}
long long int Dinic(int s,int t){
   long long int flow=0;
   while(BFS(s,t)!=-1){
      memcpy(tmphead,head,sizeof head);
      while(true){
         memset(visit,0,sizeof visit);
         long long int f=DFS(s,INF,t);
         if(!f)   break;
         flow+=f;
      }
   }
   return flow;
}

int dp[101][101];
struct SP{
	int x,a,f,p,pro,idx;
	bool operator<(const SP& rhs)const{
		return a<rhs.a;
	}
}sp[100001];

struct BA{
	int x,d,g;
	bool operator<(const BA& rhs)const{
		return d<rhs.d;
	}
}ba[100001];
int cur[101];
int s1[1001],s2[1001];
map<int,int> mp;
set<int> st;
int main(){
	ios_base::sync_with_stdio(0);
	cin.tie(0);
	int n,m;
	cin>>n>>m;
	init();
	for(int i=1;i<=100;i++)
		cur[i]=-1e9;
	for(int i=1;i<=100;i++)
		for(int j=1;j<=100;j++)
			dp[i][j]=1e9+1;
	for(int i=1,u,v;i<=m;i++){
		cin>>u>>v;
		dp[u][v]=dp[v][u]=1;
	}
	for(int i=1;i<=100;i++)
		dp[i][i]=0;
	for(int k=1;k<=n;k++)
		for(int i=1;i<=n;i++)
			for(int j=1;j<=n;j++)
				dp[i][j]=min(dp[i][j],dp[i][k]+dp[k][j]);
	int s,b,k;
	cin>>s>>b>>k;
	for(int i=1;i<=s;i++){
		cin>>sp[i].x>>sp[i].a>>sp[i].f>>sp[i].p;
		sp[i].pro=-1e9;
		sp[i].idx=i;
	}
	sort(sp+1,sp+s+1);
	for(int i=1;i<=b;i++){
		cin>>ba[i].x>>ba[i].d>>ba[i].g;
	}
	sort(ba+1,ba+b+1);
	int pb=1;
	for(int i=1;i<=s;i++){
		while(pb<=b&&ba[pb].d<=sp[i].a)
			cur[ba[pb].x]=max(cur[ba[pb].x],ba[pb].g),pb++;
		for(int j=1;j<=n;j++)
			if(dp[j][sp[i].x]<=sp[i].f)
				sp[i].pro=max(sp[i].pro,cur[j]);
	}
	for(int i=1;i<=k;i++){
		cin>>s1[i]>>s2[i];
		st.insert(s1[i]);st.insert(s2[i]);
	}
	int stp=0;
	for(int it:st)
		mp[it]=++stp;
	long long int ans=0;
	for(int i=1;i<=s;i++){
		sp[i].pro-=sp[i].p;
		if(sp[i].pro>=0)	ans+=sp[i].pro;
		if(mp.find(sp[i].idx)!=mp.end()){
			if(sp[i].pro>0)
				addedge(stp+1,mp[sp[i].idx],sp[i].pro);
			else if(sp[i].pro<0)
				addedge(mp[sp[i].idx],stp+2,-sp[i].pro);
		}
	}
	for(int i=1;i<=k;i++)
		addedge(mp[s1[i]],mp[s2[i]],INF);
	cout<<ans-Dinic(stp+1,stp+2)<<endl;
}

#include<bits/stdc++.h>
#define re register
#define inc(i,j,k) for(re int i=j;i<=k;i++)
#define dec(i,j,k) for(re int i=j;i>=k;i--)
#define ll long long
using namespace std;
const int MAXN=105;
const int MAXM=100005;
const int inf=2147483647;
inline int read(){
	int x=0,f=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while('0'<=ch&&ch<='9'){x=x*10+ch-'0',ch=getchar();}
	return f*x;
}
int n,m,s,b,dis[MAXN][MAXN],a,c,x,f,p,val,d,g,dp[MAXM],ru[MAXM],cnt=1,head[MAXM],t,S,T,dep[MAXM],tmp;
ll ans;
inline void floyd(){
	inc(k,1,n){
		inc(i,1,n){
			inc(j,1,n) dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
		}
	}
}
struct spaceship{
	int a,f,p,val,num;
	bool flag;
	spaceship(int aa,int ff,int pp,int vval,bool fflag,int nnum){a=aa,f=ff,p=pp,val=vval,flag=fflag,num=nnum;}
};
struct castal{
	int d,g;
	castal(int dd,int gg){d=dd,g=gg;}
};
vector<spaceship> ship[MAXN];
vector<castal> cas[MAXN],cass[MAXN];
bool cmp1(spaceship x,spaceship y){return x.a<y.a;}
bool cmp2(castal x,castal y){return x.d<y.d;}
struct egde{
	int to,nxt,flow;
}e[MAXM<<2];
bool use[MAXM];
inline void add(int a,int b,int c){
	e[++cnt].to=b;
	e[cnt].nxt=head[a];
	head[a]=cnt;
	e[cnt].flow=c;
}
bool bfs(){
	queue<int> q;
	inc(i,0,s+1) dep[i]=-1;
	q.push(S),dep[S]=1;
	while(q.size()){
		int u=q.front();
		q.pop();
		for(re int i=head[u];i;i=e[i].nxt){
			int v=e[i].to;
			if(dep[v]==-1&&e[i].flow){
				dep[v]=dep[u]+1;
				q.push(v);
			}
		}
	}
	return dep[T]!=-1;
}
int dfs(int u,int f){
	if(u==T) return f;
	int res=f,k=0;
	for(re int i=head[u];i;i=e[i].nxt){
		int v=e[i].to;
		if(dep[u]+1==dep[v]&&e[i].flow){
			k=dfs(v,min(f,e[i].flow));
			if(!k) dep[v]=-1;
			e[i].flow-=k;
			e[i^1].flow+=k;
			res-=k;
		}
	}
	return f-res;
}
int main(){
	n=read(),m=read();
	inc(i,1,n){
		inc(j,1,n) dis[i][j]=1000;
	}
	inc(i,1,m){
		a=read(),c=read();
		dis[c][a]=dis[a][c]=1;
	}
	floyd();
	s=read(),b=read(),t=read();
	S=0,T=s+1;
	inc(i,1,s){
		x=read(),a=read(),f=read(),p=read();
		ship[x].push_back(spaceship(a,f,p,0,0,i));
	}
	inc(i,1,b){
		x=read(),d=read(),g=read();
		cas[x].push_back(castal(d,g));
	}
	inc(i,1,n) sort(ship[i].begin(),ship[i].end(),cmp1);
	inc(i,1,n) sort(cas[i].begin(),cas[i].end(),cmp2);
	inc(i,1,n){
		for(re int j=0;j<cas[i].size();j++){
			while(j<cas[i].size()&&cass[i].size()&&cas[i][j].g<cass[i][cass[i].size()-1].g) j++;
			if(j>=cas[i].size()) break;
			cass[i].push_back(cas[i][j]);
		}
	}
	inc(i,1,n){
		inc(j,1,n){
			if(!cass[j].size()) continue;
			int l=-1;
			for(re int k=0;k<ship[i].size();k++){
				while(l+1<cass[j].size()&&cass[j][l+1].d<=ship[i][k].a) l++;
				if(l!=-1&&ship[i][k].f>=dis[i][j]) ship[i][k].flag=1,ship[i][k].val=max(ship[i][k].val,cass[j][l].g);
			}
		}
	}
	inc(i,1,n){
		for(re int j=0;j<ship[i].size();j++){
			use[ship[i][j].num]=ship[i][j].flag;
			dp[ship[i][j].num]=ship[i][j].val-ship[i][j].p;
			ans+=max((ll)0,(ll)dp[ship[i][j].num]);
		}
	}
	inc(i,1,t){
		a=read(),c=read();
		if(use[a]&&use[c])add(a,c,inf),add(c,a,0);
	}
	inc(i,1,s){
		if(use[i]){
			if(dp[i]>0) add(S,i,dp[i]),add(i,S,0);
			else if(dp[i]<0) add(i,T,-dp[i]),add(T,i,0);
		}
	}
	while(bfs()) while(tmp=dfs(S,inf)) ans-=(ll)tmp;
	printf("%I64d",ans);
}

#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <utility>
#include <limits>

struct base_t {
    int64_t position, defense, gold;
    friend std::istream& operator >> (std::istream& flux, base_t& b) {
        flux >> b.position >> b.defense >> b.gold;
        return flux;
    }
    bool operator < (const base_t& b) const {
        //if (this->defense != b.defense)
            return this->defense < b.defense;
        //return this->gold < b.gold;
    }
};

struct ship_t {
    int64_t position, strength, fuel, price;
    friend std::istream& operator >> (std::istream& flux, ship_t& s) {
        flux >> s.position >> s.strength >> s.fuel >> s.price;
        return flux;
    }
};

struct Flow_Edge {
    int from, to;
    int64_t capacity, flow = 0LL;
    Flow_Edge (const int& from, const int& to, const int64_t& capacity): from (from), to (to), capacity (capacity) {
    }
};

constexpr int64_t Inf = 1e12 + 42;
using Ip = std::pair <int64_t, int64_t>;
using Vi = std::vector <int>;
using VVi = std::vector <Vi>;
using Vi64 = std::vector <int64_t>;
using VVi64 = std::vector <Vi64>;
using VIp = std::vector <Ip>;
using VVIp = std::vector <VIp>;
using Vf = std::vector <Flow_Edge>;
using Vs = std::vector <ship_t>;
using Vb = std::vector <base_t>;
using Qi = std::queue <int>;

struct Dinic {
    Vf Edges;
    VVi Adj;
    int n, s, t;
    Vi Level, Ptr;
    Qi Q;
    Dinic (const int& n, const int& s, const int& t): n (n), s (s), t (t) {
        Adj.resize (n), Level.resize (n), Ptr.resize (n);
    }
    void add_edge (const int& u, const int& v, const int64_t& cap) {
        Edges.emplace_back (Flow_Edge (u, v, cap));
        Adj[u].emplace_back (Edges.size () - 1);
        Edges.emplace_back (Flow_Edge (v, u, 0));
        Adj[v].emplace_back (Edges.size () - 1);
    }
    bool bfs () {
        while (!Q.empty ()) {
            int v = Q.front (); Q.pop ();
            for (const auto& id: Adj[v]) {
                if (Edges[id].capacity - Edges[id].flow < 1)
                    continue;
                if (Level[Edges[id].to] != -1)
                    continue;
                Level[Edges[id].to] = Level[v] + 1;
                Q.push (Edges[id].to);
            }
        }
        return Level[t] != -1;
    }
    int64_t dfs (const int& v, const int64_t& pushed) {
        if (!pushed)
            return 0LL;
        if (v == t)
            return pushed;
        for (int& cid = Ptr[v]; cid < (int)Adj[v].size (); ++ cid) {
            int id = Adj[v][cid], u = Edges[id].to;
            if (Level[v] + 1 != Level[u] || Edges[id].capacity - Edges[id].flow < 1)
                continue;
            int64_t transport = dfs (u, Edges[id].capacity - Edges[id].flow);
            if (!transport)
                continue;
            Edges[id].flow += transport;
            Edges[id ^ 1].flow -= transport;
            return transport;
        }
        return 0LL;
    }
    int64_t max_flow () {
        int64_t f = 0LL;
        while (true) {
            std::fill (Level.begin (), Level.end (), -1);
            Level[s] = 0;
            Q.push (s);
            if (!bfs ())
                break;
            std::fill (Ptr.begin (), Ptr.end (), 0);
            while (int64_t pushed = dfs (s, Inf))
                f += pushed;
        }
        return f;
    }
};

int n, m, u, v, s, b, k;
Vi64 Value;
VVi64 Cost;
Vs Ships;
Vb Bases;
VVIp Bases_at;

int main () {
    std::cin >> n >> m;
    Cost.assign (n + 1, Vi64 (n + 1, Inf));
    for (int i = 1; i <= m; ++ i)
        std::cin >> u >> v, Cost[u][v] = Cost[v][u] = std::min (Cost[u][v], 1LL);

    for (int k = 1; k <= n; ++ k)
        for (int i = 1; i <= n; ++ i)
            for (int j = 1; j <= n; ++ j)
                Cost[i][j] = std::min (Cost[i][j], Cost[i][k] + Cost[k][j]);

    std::cin >> s >> b >> k;
    Value.resize (s + 1), Bases_at.resize (n + 1);
    Ships.resize (s + 1), Bases.resize (b + 1);
    for (int i = 1; i <= s; ++ i)
        std::cin >> Ships[i];
    for (int i = 1; i <= b; ++ i)
        std::cin >> Bases[i];

    std::sort (Bases.begin () + 1, Bases.end ());
    for (int i = 1; i <= b; ++ i) {
        int pos = Bases[i].position;
        if (Bases_at[pos].empty () || Bases_at[pos].back ().second < Bases[i].gold)
            Bases_at[pos].emplace_back (std::make_pair (Bases[i].defense, Bases[i].gold));
    }

    int source = 0, sink = s + 1;
    Dinic dinic (s + 2, source, sink);
    int64_t ans = 0LL;
    for (int i = 1; i <= s; ++ i) {
        bool found = false;
        for (int p = 1; p <= n; ++ p) {
            if (Cost[Ships[i].position][p] > Ships[i].fuel)
                continue;
            auto it = std::upper_bound (Bases_at[p].begin (), Bases_at[p].end (), std::make_pair (Ships[i].strength, Inf));
            if (it != Bases_at[p].begin ())
                -- it, found = true, Value[i] = std::max (Value[i], it->second);
        }
        Value[i] -= Ships[i].price;
        if (!found)
            Value[i] = -Inf;
        if (Value[i] >= 0)
            ans += Value[i], dinic.add_edge (source, i, Value[i]);
        else
            dinic.add_edge (i, sink, -Value[i]);
    }

    for (int i = 1; i <= k; ++ i)
        std::cin >> u >> v,
        dinic.add_edge (u, v, Inf);

    std::cout << ans - dinic.max_flow ();

    return 0;
}

#include <iostream>
#include <vector>
#include <algorithm>
#include <tuple>
#include <queue>
using namespace std;
typedef long long ll;
typedef tuple<int, int, int> event;

const int MAXN = 100100;
const ll INFTY = 1LL<<60;
int N, M, S, B, K;
ll dist[105][105];
ll maxG[105];
int spos[MAXN], fuel[MAXN], price[MAXN];
int bpos[MAXN], gold[MAXN];
ll profit[MAXN];
vector<event> E;

struct Edge
{
    int u, v;
    ll cap, flow;
    Edge() {}
    Edge(int u, int v, ll cap): u(u), v(v), cap(cap), flow(0) {}
};

struct Dinic
{
    const static ll INFTY = 1LL<<60;
    int N;
    vector<Edge> E;
    vector<vector<int> > g;
    vector<int> d, pt;

    Dinic(int N): N(N), E(0), g(N), d(N), pt(N) {}

    void addEdge(int u, int v, ll cap)
    {
        if (u != v)
        {
            E.push_back(Edge(u, v, cap));
            g[u].push_back(E.size() - 1);
            E.push_back(Edge(v, u, 0));
            g[v].push_back(E.size() - 1);
        }
    }

    bool BFS(int S, int T)
    {
        queue<int> q;
        q.push(S);
        fill(d.begin(), d.end(), N + 1);
        d[S] = 0;

        while (!q.empty())
        {
            int u = q.front();
            q.pop();
            if (u == T)
                break;
            for (int k : g[u])
            {
                Edge &e = E[k];
                if (e.flow < e.cap && d[e.v] > d[e.u] + 1)
                {
                    d[e.v] = d[e.u] + 1;
                    q.push(e.v);
                }
            }
        }

        return d[T] != N + 1;
    }

    ll DFS(int u, int T, ll flow = INFTY)
    {
        if (u == T || flow == 0)
            return flow;

        for (int &i = pt[u]; i < g[u].size(); ++i)
        {
            Edge &e = E[g[u][i]];
            Edge &oe = E[g[u][i]^1];
            if (d[e.v] == d[e.u] + 1)
            {
                ll amt = min(flow, e.cap - e.flow);
                if (ll pushed = DFS(e.v, T, amt))
                {
                    e.flow += pushed;
                    oe.flow -= pushed;
                    return pushed;
                }
            }
        }

        return 0;
    }

    ll maxFlow(int S, int T)
    {
        ll total = 0;
        while (BFS(S, T))
        {
            fill(pt.begin(), pt.end(), 0);
            while (ll flow = DFS(S, T))
                total += flow;
        }
        return total;
    }
};

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);

    cin >> N >> M;
    for (int i = 1; i <= N; i++)
        for (int j = i + 1; j <= N; j++)
            dist[i][j] = dist[j][i] = INFTY;
    for (int i = 0, a, b; i < M; i++)
    {
        cin >> a >> b;
        dist[a][b] = dist[b][a] = 1;
    }
    for (int k = 1; k <= N; k++)
        for (int i = 1; i <= N; i++)
            for (int j = 1; j <= N; j++)
                dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);

    cin >> S >> B >> K;
    for (int i = 1, a; i <= S; i++)
    {
        cin >> spos[i] >> a >> fuel[i] >> price[i];
        E.emplace_back(a, 1, i);
    }
    for (int i = 1, d; i <= B; i++)
    {
        cin >> bpos[i] >> d >> gold[i];
        E.emplace_back(d, 0, i);
    }

    for (int i = 1; i <= S; i++)
        profit[i] = -INFTY;
    sort(E.begin(), E.end());
    for (event e : E)
    {
        int power, type, idx;
        tie(power, type, idx) = e;
        if (type == 0) //base
            maxG[bpos[idx]] = max(maxG[bpos[idx]], (ll)gold[idx]);
        else //ship
        {
            for (int i = 1; i <= N; i++)
                if (fuel[idx] >= dist[spos[idx]][i])
                    profit[idx] = max(profit[idx], maxG[i] - price[idx]);
        }
    }

    Dinic dinic(S + 2);
    ll ans = 0;
    for (int i = 1; i <= S; i++)
    {
        if (profit[i] > 0)
        {
            dinic.addEdge(0, i, profit[i]);
            ans += profit[i];
        }
        else
            dinic.addEdge(i, S + 1, -profit[i]);
    }
    for (int i = 0, a, b; i < K; i++)
    {
        cin >> a >> b;
        dinic.addEdge(a, b, INFTY);
    }
    cout << ans - dinic.maxFlow(0, S + 1) << "\n";

    return 0;
}

/*
    Author : manu_sy
*/
#include "bits/stdc++.h"
using namespace std;

/** Template Begins **/
#define int ll
typedef long long        ll;
typedef pair<int,int>    PII;

#define IOS         ios_base::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
#define endl        '\n'
#define pb          push_back
#define F           first
#define S           second
#define mp          make_pair
#define all(a)      (a).begin(), (a).end()
#define FOR(i,a,b)  for(int i=a;i<=b;i++)
#define LP(i,n)     for(int i=0;i< n;i++)

/* Debug */

template<class L, class R> ostream &operator<<(ostream &os, pair<L,R> P) {
  return os << "(" << P.F << "," << P.S << ")";
}

template<class T> ostream &operator<<(ostream& os, vector<T> V) {
  os << "["; for (auto vv : V) os << vv << ","; return os << "]";
}

template<class TH> void _dbg(const char *sdbg, TH h){ cerr << sdbg << '=' << h << endl; }

template<class TH, class... TA> void _dbg(const char *sdbg, TH h, TA... a) {
  while(*sdbg!=',') cerr << *sdbg++;
  cerr<<'='<<h<<','; _dbg(sdbg+1, a...);
}

#ifdef LOCALI
#define debug(...) _dbg(#__VA_ARGS__, __VA_ARGS__)
#else
#define debug(...) (__VA_ARGS__)
#define cerr if(0)cout
#endif

/* Debug Ends */

const int NN = 1e2+7, N = 1e5+7, NNN = 2e3+7;
const int INF1 = 1e9+100;

/** Template Ends **/

int n, m, dist[NN][NN], s, b, k;
bool mark[N];
int sx[N], sa[N], sf[N], sp[N];
vector<PII> base[NN];
int profit[N];
vector<int> posp, negp;
int d1[N], d2[N], aa, bb;
ll ans;

void fill_graph()
{
    FOR(i,1,n) FOR(j,1,n) dist[i][j] = (i == j ? 0 : INF1);
    LP(i,m)
    {
        int u, v; cin >> u >> v;
        dist[u][v] = dist[v][u] = min(dist[u][v], 1LL);
    }
    FOR(k,1,n) FOR(i,1,n) FOR(j,1,n) dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
}
void simplify_bases()
{
    FOR(i,1,n) sort(all(base[i]));
    FOR(i,1,n)
    {
        int mg = 0;
        for (auto &bs: base[i]) bs.S = max(bs.S, mg), mg = bs.S;
        debug(i, base[i]);
    }
}
void calc_profit()
{
    FOR(i,1,s)
    {
        profit[i] = -INF1;
        FOR(j,1,n) if (dist[sx[i]][j] <= sf[i])
        {
            int pos = upper_bound(all(base[j]), mp(sa[i], -INF1)) - base[j].begin() - 1;
            if (pos == -1)  continue;
            profit[i] = max(profit[i], base[j][pos].S - sp[i]);
        }
        debug(i, profit[i]);
    }
}
void get_dep()
{
    LP(i,k)
    {
        debug(d1[i], d2[i]);
        cin >> d1[i] >> d2[i];
        mark[d1[i]] = mark[d2[i]] = true;
    }
    FOR(i,1,s)
    {
        ans += max(0LL, profit[i]);
        if (!mark[i]) continue;
        if (profit[i] >= 0) posp.pb(i);
        else                negp.pb(i);
    }
    sort(all(posp));   sort(all(negp));
    debug(posp); debug(negp);
}
namespace Maxflow{
    const int maxn=2022;
    const int maxm=66666;
    const int inf=INF1;

    int g[maxn],to[maxm],np[maxm],cp;
    int n,u,v,now,source,sink;
    int sum,cap[maxm],a[maxn];
    int d[maxn],p[maxn],cur[maxn],cnt[maxn];

    void add_edge(int x,int y,int z){
        // printf("%d - %d: %d\n",x,y,z);
        cap[cp]=z;to[cp]=y;np[cp]=g[x];g[x]=cp++;cap[cp]=0;to[cp]=x;np[cp]=g[y];g[y]=cp++;
    }

    void init(){
        cp=2; memset(g,0,sizeof(g));
    }
    int maxflow(){
        sum=0;
        for(u=1;u<=n;u++)cur[u]=g[u]; a[u=source]=inf; memset(d,0,sizeof(int)*(n+1)); memset(cnt,0,sizeof(int)*(n+1)); cnt[0]=n;
        while(d[source]<n)
        {
            for(now=cur[u];now;now=np[now])if(cap[now]&&d[v=to[now]]+1==d[u])break; cur[u]=now;
            if(now)
            {
                p[v]=now; a[v]=cap[now]; if(a[v]>a[u])a[v]=a[u];
                if((u=v)==sink)
                {
                    do{cap[p[u]]-=a[sink]; cap[p[u]^1]+=a[sink]; u=to[p[u]^1];}while(u!=source);
                    sum+=a[sink]; a[source]=inf;
                }
            }
            else
            {
                if(--cnt[d[u]]==0)break; d[u]=n; cur[u]=g[u];
                for(now=g[u];now;now=np[now]) if(cap[now] && d[u]>d[to[now]]+1) d[u]=d[to[now]]+1;
                cnt[d[u]]++;
                if(u!=source)u=to[p[u]^1];
            }
        }
    //    printf("maxflow\n");
        return sum;
    }
}
int findp(int s1) {
    if (profit[s1] >= 0)    return lower_bound(all(posp), s1) - posp.begin() + 1;
    else                    return lower_bound(all(negp), s1) - negp.begin() + aa + 1;
}
signed main() {

    IOS;
    cin >> n >> m;
    fill_graph();
    cin >> s >> b >> k;
    FOR(i,1,s) cin >> sx[i] >> sa[i] >> sf[i] >> sp[i];
    LP(i,b)
    {
        int x, d, g;    cin >> x >> d >> g;
        base[x].pb(mp(d, g));
    }
    simplify_bases();
    calc_profit();
    get_dep();
    aa = posp.size(), bb = negp.size();

    Maxflow::init();
    Maxflow::n = aa + bb + 2;
    Maxflow::source = 0, Maxflow::sink = aa + bb + 1;
    LP(i,aa) Maxflow::add_edge(0, i + 1, profit[posp[i]]);
    LP(i,bb) Maxflow::add_edge(aa + i + 1, Maxflow::sink, -profit[negp[i]]);

    LP(i,k)
    {
        int s1 = d1[i], s2 = d2[i];
        int x1 = findp(s1), x2 = findp(s2);
        debug(s1, s2, x1, x2);
        Maxflow::add_edge(x1, x2, INF1);
    }
    int ff = Maxflow::maxflow();
    debug(ff);
    cout << ans - ff << endl;

    return 0;
}

#pragma GCC optimize("O3")
#include <bits/stdc++.h>

using namespace std;

#define sim template<class c
#define ris return *this
#define dor > debug & operator<<
#define eni(x) sim>typename \
  enable_if<sizeof dud<c>(0) x 1, debug&>::type operator<<(c i) {
sim> struct rge { c b, e; };
sim> rge<c> range(c i, c j) { return rge<c>{i, j}; }
sim> auto dud(c*x) -> decltype(cerr<<*x, 0);
sim> char dud(...);
struct debug {
#ifdef LOCAL
~debug() { cerr << endl; }
eni(!=) cerr << boolalpha << i; ris; }
eni(==) ris << range(begin(i), end(i)); }
sim, class b dor (pair<b,c> d) {
  ris<<"("<<d.first<<", "<<d.second<<")";
}
sim dor(rge<c> d) {
  *this<<"[";
  for (auto it = d.b; it != d.e; ++it)
    *this << ", " + 2 * (it == d.b) << *it;
  ris <<" ]";
}
#else
sim dor(const c&) { ris; }
#endif
};
#define imie(...) " [" << #__VA_ARGS__ ": " << (__VA_ARGS__) << "] "

using ll = long long;
#define int ll
#define PB push_back
#define MP make_pair
#define PII pair<int, int>
#define SZ(x) ((int)(x).size())
#define FOR(i,a,b) for (int i = (a); i <= (b); ++i)
#define REP(i,n) FOR(i,0,(int)(n)-1)
#define VI vector<int>
using pii = pair<int, int>;
using pll = pair<ll, ll>;
using vi = vector<int>;
using vll = vector<ll>;

struct Dinic {
  struct Edge { int v, c, inv; };
public:
  Dinic() : n(-1) {}
  void AddEdge(int a, int b, int cap, int bi_dir) {
    if (n < max(a, b)) {
      n = max(n, max(a, b));
      ResizeVectors();
    }
    e_orig[a].PB(Edge{b, cap, SZ(e_orig[b])});
    e_orig[b].PB(Edge{a, bi_dir * cap, SZ(e_orig[a]) - 1});
  }
  int MaxFlow(int s, int t) {
    if (t > n || s > n) {
      n = max(s, t);
      ResizeVectors();
    }
    e = e_orig; int result = 0;
    while (Bfs(s, t)) {
      fill_n(beg.begin(), n + 1, 0);
      result += Dfs(s, t, kInf);
    }
    return result;
  }
  vector<bool> MinCut(int s, int t) {
    assert(!Bfs(s, t));
    vector<bool> res(n + 1);
    FOR (i, 0, n) { res[i] = (dis[i] <= n); }
    return res;
  }

  vector<PII> EdgeCut(int s, int t) {
    vector<bool> left_part = MinCut(s, t);
    vector<PII> cut;
    FOR (v, 0, n) {
      for (auto edge : e_orig[v]) {
        if (edge.c != 0 && left_part[v] && !left_part[edge.v]) {
          cut.PB({v, edge.v});
        }
      }
    }
    return cut;
  }
private:
  int n;
  vector<vector<Edge>> e_orig, e;
  VI dis, beg;

  bool Bfs(int s, int t) {
    fill_n(dis.begin(), n + 1, n + 1);
    dis[s] = 0;
    VI que;
    que.push_back(s);
    REP (i, SZ(que)) {
      int v = que[i];
      for (auto edge : e[v]) {
        int nei = edge.v;
        if (edge.c && dis[nei] > dis[v] + 1) {
          dis[nei] = dis[v] + 1;
          que.push_back(nei);
          if (nei == t) { return true; }
        }
      }
    }
    return false;
  }
  int Dfs(int v, int t, int min_cap) {
    int result = 0;
    if (v == t || min_cap == 0) { return min_cap; }
    for (int& i = beg[v]; i < SZ(e[v]); i++) {
      int nei = e[v][i].v, c = e[v][i].c;
      if (dis[nei] == dis[v] + 1 && c > 0) {
        int flow_here = Dfs(nei, t, min(min_cap, c));
        result += flow_here;
        min_cap -= flow_here;
        e[v][i].c -= flow_here;
        e[nei][e[v][i].inv].c += flow_here;
      }
      if (min_cap == 0) { break; }
    }
    return result;
  }

  void ResizeVectors() {
    e_orig.resize(n + 2);
    beg.resize(n + 2);
    dis.resize(n + 2);
  }

  #ifndef int
  #warning
  #endif
  static const int kInf = 1e18; // UWAZAC, JESLI NIE INT = LONG LONG
};

const int MaxN = 2048;
const int MaxItems = 5e5;

int n, m;
vi adj[MaxN];
int s, b, k, h;
int dist[MaxN][MaxN];
vector<pii> at_vert[MaxN];

int sp_loc[MaxItems], sp_atk[MaxItems], sp_fuel[MaxItems], sp_price[MaxItems];
int bs_loc[MaxItems], bs_def[MaxItems], bs_gold[MaxItems];

vi dep_adj[MaxItems];
bool any_dep[MaxItems];
int dep_idx[MaxItems];

int32_t main() {
  scanf("%lld%lld", &n, &m);
  for (int i = 0; i < n; ++i) {
    for (int j = 0; j < n; ++j) {
      dist[i][j] = 2e9;
    }
    dist[i][i] = 0;
  }

  for (int i = 0; i < m; ++i) {
    int u, v;
    scanf("%lld%lld", &u, &v);
    adj[u].push_back(v);
    adj[v].push_back(u);
    if (u != v) {
      dist[u][v] = dist[v][u] = 1;
    }
  }

  for (int k = 1; k <= n; ++k) {
    for (int i = 1; i <= n; ++i) {
      for (int j = 1; j <= n; ++j) {
        dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
      }
    }
  }

  scanf("%lld%lld%lld", &s, &b, &k);

  for (int i = 0; i < s; ++i) {
    scanf("%lld%lld%lld%lld", &sp_loc[i], &sp_atk[i], &sp_fuel[i], &sp_price[i]);
  }
  for (int i = 0; i < b; ++i) {
    scanf("%lld%lld%lld", &bs_loc[i], &bs_def[i], &bs_gold[i]);
    at_vert[bs_loc[i]].emplace_back(bs_def[i], bs_gold[i]);
  }

  for (int v = 1; v <= n; ++v) {
    auto &X = at_vert[v];
    sort(X.begin(), X.end());

    const int sz = X.size();
    int cur_max = -1;
    int ptr = 0;
    for (int i = 0; i < sz; ++i) {
      if (X[i].second <= cur_max) { continue; }
      X[ptr++] = X[i];
      cur_max = X[i].second;
    }
    X.resize(ptr);

    debug() << imie(v) << imie(X);
  }

  const int kSmallInf = 2e16;
  const ll kLargeInf = 2e16;

  vll sp_best(s, -kLargeInf);
  for (int i = 0; i < s; ++i) {
    for (int v = 1; v <= n; ++v) {
      if (sp_fuel[i] < dist[sp_loc[i]][v]) { continue; }
      const int atk = sp_atk[i];
      auto iter =
        lower_bound(at_vert[v].begin(), at_vert[v].end(),
                    pii(atk, kSmallInf));
      if (iter == at_vert[v].begin()) {
        continue;
      } else {
        int bnd = prev(iter)->second;
        sp_best[i] = max(sp_best[i], (ll)bnd - sp_price[i]);
      }
    }
    debug() << imie(i) << imie(sp_best[i]);
  }

  for (int i = 0; i < k; ++i) {
    int u, v;
    scanf("%lld%lld", &u, &v);
    --u; --v;
    any_dep[u] = any_dep[v] = true;
    dep_adj[u].PB(v);
  }

  ll ans = 0;
  int curidx = 0;
  for (int i = 0; i < s; ++i) {
    if (!any_dep[i] && sp_best[i] >= 0) {
      ans += sp_best[i];
    }
    /*if (any_dep[i]) {
      dep_idx[i] = curidx++;
    }*/
    dep_idx[i] = curidx++;
  }

  Dinic dinic;
  const int source = curidx;
  const int sink = source + 1;

  debug() << imie(source) << imie(sink);

  for (int i = 0; i < s; ++i) {
    if (!any_dep[i]) { continue; }
    if (sp_best[i] >= 0) {
      dinic.AddEdge(source, dep_idx[i], sp_best[i], 0);
      ans += sp_best[i];
    } else {
      dinic.AddEdge(dep_idx[i], sink, -sp_best[i], 0);
    }

    for (int j : dep_adj[i]) {
      dinic.AddEdge(dep_idx[i], dep_idx[j], kLargeInf, 0);
    }
  }

  const ll flow = dinic.MaxFlow(source, sink);
  ans -= flow;
  assert(ans >= 0);

  printf("%lld\n", ans);

}

#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define ULL unsigned long long
#define mp make_pair
#define pb push_back
#define pii pair<int,int>
#define pll pair<LL,LL>
#define x first
#define y second
#define pi acos(-1)
#define sqr(x) ((x)*(x))
#define pdd pair<double,double>
#define MEMS(x) memset(x,-1,sizeof(x))
#define MEM(x) memset(x,0,sizeof(x))
#define less Less
vector<int> v[100005];
struct Dinic{
    static const int MXN = 250000;
    struct Edge{ int v,f,re; Edge(int a,int b,int c):v(a),f(b),re(c){}};
    int n,s,t,level[MXN];
    vector<Edge> E[MXN];
    void init(int _n, int _s, int _t){
        n = _n; s = _s; t = _t;
        for (int i=0; i<=n; i++) E[i].clear();
    }
    void add_edge(int u, int v, int f){
        E[u].pb(Edge(v,f,E[v].size()));
        E[v].pb(Edge(u,0,E[u].size()-1));//direct
     //   printf("%d %d %d\n",u,v,f);
    }
    bool BFS(){
        MEMS(level);
        queue<int> que;
        que.push(s);
        level[s] = 0;
        while (!que.empty()){
            int u = que.front(); que.pop();
            for (auto it : E[u]){
                if (it.f > 0 && level[it.v] == -1){
                    level[it.v] = level[u]+1;
                    que.push(it.v);
                }
            }
        }
        return level[t] != -1;
    }
    LL DFS(int u, LL nf){
        if (u == t) return nf;
        LL res = 0;
        for (auto &it : E[u]){
            if (it.f > 0 && level[it.v] == level[u]+1){
                LL tf = DFS(it.v, min(nf,(LL)it.f));
                res += tf; nf -= tf; it.f -= tf;
                E[it.v][it.re].f += tf;
                if (nf == 0) return res;
            }
        }
        if (!res) level[u] = -1;
        return res;
    }
    LL flow(LL res=0){
        while ( BFS() )
        res += DFS(s,1e18);
        return res;
    }
}flow;
int vis[100005],s;
void go(int x,int t){
    for(auto it:v[x]){
        if(vis[it]!=t){
            flow.add_edge(t,it+s,2e9);
            vis[it]=t;
            go(it,t);
        }
    }
}
int main(){
    int n,m;
    scanf("%d %d",&n,&m);
    int dis[105][105];
    for(int i = 1;i<=n;i++){
        for(int j = 1;j<=n;j++)
            dis[i][j]=1e9;
        dis[i][i]=0;
    }
    for(int i = 0;i<m;i++){
        int x,y;
        scanf("%d %d",&x,&y);
        dis[x][y]=dis[y][x]=1;
    }
    for(int i = 1;i<=n;i++){
        for(int j = 1;j<=n;j++){
            for(int k = 1;k<=n;k++){
                dis[j][k]=min(dis[j][i]+dis[i][k],dis[j][k]);
            }
        }
    }
    int B,k;
    scanf("%d %d %d",&s,&B,&k);
    int x[100005],a[100005],f[100005],p[100005];
    vector<pii> base[105];
    for(int i = 1;i<=s;i++){
        scanf("%d %d %d %d",&x[i],&a[i],&f[i],&p[i]);
    }
    for(int i = 0;i<B;i++){
        int a,b,c;
        scanf("%d %d %d",&a,&b,&c);
        base[a].pb(mp(b,c));
    }
    for(int i = 1;i<=n;i++){
    //    base[i].pb(mp(0,0));
        sort(base[i].begin(),base[i].end());
        vector<pii> tmp=base[i];
        base[i].clear();
        base[i].pb(mp(0,0));
        for(auto it:tmp){
            if(it.y>base[i].back().y){
                base[i].pb(it);
            }
        }
       // for(auto it:base[i])
       // printf("%d %d ",it.x,it.y);
       // printf("\n");
    }
    int val[100005];
    for(int i = 1;i<=s;i++){
        val[i]=-p[i];
        for(int j = 1;j<=n;j++){
            if(dis[x[i]][j]<=f[i]){
              //  printf("%d %d\n",i,j);
                val[i]=max(val[i],(lower_bound(base[j].begin(),base[j].end(),mp(a[i],1000000009))-1)->y-p[i]);
                //printf("%d\n",(lower_bound(base[i].begin(),base[i].end(),mp(a[i],1000000000))-1)->y)
            }
        }
     //   printf("%d\n",val[i]);
    }
    for(int i = 0;i<k;i++){
        int a,b;
        scanf("%d %d",&a,&b);
        v[b].pb(a);
    }
    flow.init(2*s+10,0,2*s+1);
    LL ans=0;
    for(int i =1;i<=s;i++){
        if(val[i]>0){
            ans+=val[i];
            flow.add_edge(i+s,2*s+1,val[i]);
        }
        else if(val[i]<0){
            flow.add_edge(0,i,-val[i]);
            go(i,i);
        }

    }
  //  printf("%lld\n",ans);
    printf("%lld\n",ans-flow.flow());
}

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef ll F;
const int N    = 1e2 + 10;
const int maxs = 1e5 + 10;
const int maxn = 2e3 + 10;
const int maxm = 6e3 + 10;
const ll INF  = 2e13;
const F  INF_CAP = INF;

struct spaceship{
    int x,a,f,p;
}sp[maxs];
struct base {
    int d,g;
    bool operator < (const base& b)const {
        return d < b.d;
    }
};

ll best_goal[maxs];

vector<base> ba[N];
vector<int>  pre[N];
vector<int>  g[maxs];
bool used[maxs];
int w[N][N],id[maxs];

struct Dinic{
    int n,m,s,t,pos;
    int d[maxn],head[maxn],que[maxn],ptr[maxn];
    int to[maxm],nxt[maxm];
    F  cap[maxm];
    void init() {
        memset(head,-1,sizeof head);
    }
    void addedge(int a,int b,F c) {
//        printf("%d %d %lld\n",a,b,c);
//        printf("%d\n",m);
        cap[m] = c;to[m] = b;nxt[m] = head[a];head[a] = m++;
        cap[m] = 0;to[m] = a;nxt[m] = head[b];head[b] = m++;
    }
    bool bfs() {
        pos = 0;
        memset(d,-1,sizeof d);
        que[pos++] = s;
        d[s] = 0;
        for(int i = 0;i < pos;i++) {
            int x = que[i];
            for(int u = head[x];~u;u = nxt[u]) {
                if(d[to[u]] == -1&&cap[u]) {
                    d[to[u]] = d[x] + 1;
                    que[pos++] = to[u];
                }
            }
        }
        return d[t] != -1;
    }
    F dfs(int o,F mi) {
        if(o == t||mi == 0) return mi;
        F res = 0;
        for(int &x = ptr[o];~x;x = nxt[x]) if(d[to[x]] == d[o] + 1&&cap[x]){
            F tmp = dfs(to[x],min(mi,cap[x]));
            cap[x] -= tmp;
            cap[x^1] += tmp;
            mi -= tmp;
            res += tmp;
            if(mi == 0) return 0;
        }
        return res;
    }
    F maxflow(int s,int t) {
        this->s = s;this->t = t;
        F res = 0;
        while(bfs()) {
            memcpy(ptr,head,sizeof head);
            res += dfs(s,INF_CAP);
        }
        return res;
    }
}D;

int main() {
    D.init();
    int n,m,s,b,k;
    scanf("%d%d",&n,&m);
    for(int i = 1;i <= n;i++) fill(w[i] + 1,w[i] + 1 + n,n),w[i][i] = 0;
    for(int i = 0;i < m;i++) {
        int a,b;
        scanf("%d%d",&a,&b);
        w[b][a] = w[a][b] = min(w[a][b],1);
    }
    for(int d = 1;d <= n;d++) {
        for(int i = 1;i <= n;i++) {
            for(int j = 1;j <= n;j++) {
                w[i][j] = min(w[i][j],w[i][d] + w[d][j]);
            }
        }
    }
    scanf("%d%d%d",&s,&b,&k);
    for(int i = 1;i <= s;i++) {
        scanf("%d%d%d%d",&sp[i].x,&sp[i].a,&sp[i].f,&sp[i].p);
    }
    for(int i = 0;i < b;i++) {
        int x,d,g;
        scanf("%d%d%d",&x,&d,&g);
        ba[x].push_back(base{d,g});
    }
    for(int i = 1;i <= n;i++) if(ba[i].size()){
        int sz = (int)ba[i].size();
        sort(ba[i].begin(),ba[i].end());
        pre[i].resize(sz);
        pre[i][0] = ba[i][0].g;
        for(int j = 1;j < sz;j++) pre[i][j] = max(pre[i][j-1],ba[i][j].g);
    }
    for(int i = 1;i <= s;i++) {
        best_goal[i] = -INF_CAP;
        int x = sp[i].x;
        for(int j = 1;j <= n;j++) {
            if(w[x][j] <= sp[i].f) {
                int pos = upper_bound(ba[j].begin(),ba[j].end(),base{sp[i].a,0}) - ba[j].begin();
                --pos;
                if(pos >= 0) {
                    best_goal[i] = max(best_goal[i],(ll)pre[j][pos] - sp[i].p);
                }
            }
        }
    }
    for(int i = 0;i < k;i++) {
        int a,b;
        scanf("%d%d",&a,&b);
        g[a].push_back(b);
        used[a] = used[b] = 1;
    }
    ll ans = 0;
    int cnt = 0;
    for(int i = 1;i <= s;i++) {
        if(!used[i]) {
            if(best_goal[i] > 0) ans += best_goal[i];
        }
        else {
            id[i] = ++cnt;
        }
    }

    int st = 0,ed = cnt + 1;
    cnt = 0;
    for(int i = 1;i <= s;i++) {
        if(used[i]) {
            if(best_goal[i] >= 0) ans += best_goal[i],D.addedge(st,id[i],best_goal[i]);
            else D.addedge(id[i],ed,-best_goal[i]);
            for(auto& u:g[i]) D.addedge(id[i],id[u],INF_CAP);
        }
    }
    // printf("%lld\n",ans);
    ans -= D.maxflow(st,ed);
    printf("%lld\n",ans);
    return 0;
}

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

int dist[100][100];

const int nax = 1e5+10;
vector<pair<int,int>> base[nax];
struct Ship {
  int x, a, f;
  ll p;
};

Ship ship[nax];
int has_base[100];

struct Edge {
  int end;
  ll cap;
};
vector<Edge> edges;
vector<int> node[nax];
void addEdge(int a, int b, ll w) {
  node[a].push_back(edges.size());
  edges.push_back({b,w});
  node[b].push_back(edges.size());
  edges.push_back({a,0});
}

int done[nax];
ll maxFlow(int p, int sink, ll ma = 1e18) {
  if (p == sink) return ma;
  if (ma == 0 || done[p]++) return 0;
  for (int ei : node[p]) {
    Edge&e = edges[ei];
    ll flow;
    if (e.cap && (flow=maxFlow(e.end, sink, min(ma,e.cap)))) {
      edges[ei].cap -= flow;
      edges[ei^1].cap += flow;
      return flow;
    }
  }
  return 0;
}

int has_edge[nax];

int main() {
  ios::sync_with_stdio(0); cin.tie(0);
  int n, m;
  cin >> n >> m;
  for (int i = 0; i < n; i++)
    for (int j = 0; j < n; j++)
      dist[i][j] = i==j ? 0 : 1e9;
  while (m--) {
    int a, b;
    cin >> a >> b;
    a--, b--;
    dist[a][b] = dist[b][a] = 1;
  }
  for (int k = 0; k < n; k++)
    for (int i = 0; i < n; i++)
      for (int j = 0; j < n; j++)
	dist[i][j] = min(dist[i][j], dist[i][k]+dist[k][j]);
  int ships, bases, deps;
  cin >> ships >> bases >> deps;
  for (int i = 0; i < ships; i++) {
    cin >> ship[i].x >> ship[i].a >> ship[i].f >> ship[i].p;
    ship[i].x--;
  }
  for (int i = 0; i < bases; i++) {
    int x, d, g;
    cin >> x >> d >> g;
    x--;
    base[x].push_back({d,g});
    has_base[x] = 1;
  }
  for (int i = 0; i < n; i++) {
    sort(base[i].begin(), base[i].end());
    vector<pair<int,int>> comp = {{0,0}};
    for (auto p : base[i]) {
      if (p.second <= comp.back().second) continue;
      if (p.first == comp.back().first)
	comp.pop_back();
      comp.push_back(p);
    }
    base[i] = comp;
  }

  int source = ships, sink = ships+1, N = ships+2;
  ll sum = 0;

  for (int i = 0; i < deps; i++) {
    int a, b;
    cin >> a >> b;
    a--, b--;
    addEdge(a, b, 1e18);
    has_edge[a] = has_edge[b] = 1;
  }

  for (int i = 0; i < ships; i++) {
    int most_gold = -1;
    for (int j = 0; j < n; j++) {
      if (!has_base[j] || dist[ship[i].x][j] > ship[i].f) continue;
      int gold = prev(upper_bound(base[j].begin(), base[j].end(), make_pair(ship[i].a,(int)2e9)))->second;
      most_gold = max(most_gold, gold);
    }
    if (!has_edge[i]) {
      sum += max(most_gold-ship[i].p, 0ll);
      continue;
    }

    if (most_gold == -1)
      ship[i].p = 1e15;
    else {
      addEdge(source, i, most_gold);
      sum += most_gold;
    }
    addEdge(i, sink, ship[i].p);
    //cout << i << ' ' << ship[i].p << ' ' << max(most_gold,0) << endl;
  }

  ll flow = 0;
  while (1) {
    fill_n(done, N, 0);
    ll newflow = maxFlow(source, sink);
    if (!newflow) break;
    flow += newflow;
  }
  //cout << sum << ' ' << flow << endl;
  cout << sum-flow << endl;
}

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int mod=1e9+7;
const int maxm=100+10;
const int maxn=3e5+10;
const int N=1e5+10;
const int inf=0x3f3f3f3f;
namespace io {
    const int SIZE = (1 << 21) + 1;
    char ibuf[SIZE], *iS, *iT, obuf[SIZE], *oS = obuf, *oT = oS + SIZE - 1, c, qu[55]; int f, qr;
    // getchar
    #define gc() (iS == iT ? (iT = (iS = ibuf) + fread (ibuf, 1, SIZE, stdin), (iS == iT ? EOF : *iS ++)) : *iS ++)
    // print the remaining part
    inline void flush () {
        fwrite (obuf, 1, oS - obuf, stdout);
        oS = obuf;
    }
    // putchar
    inline void putc (char x) {
        *oS ++ = x;
        if (oS == oT) flush ();
    }
    template<typename A>
    inline bool read (A &x) {
        for (f = 1, c = gc(); c < '0' || c > '9'; c = gc()) if (c == '-') f = -1;else if(c==EOF)return 0;
        for (x = 0; c <= '9' && c >= '0'; c = gc()) x = x * 10 + (c & 15); x *= f;
        return 1;
    }
    inline bool read (char &x) {
        while((x=gc())==' '||x=='\n' || x=='\r');
        return x!=EOF;
    }
    inline bool read(char *x){
        while((*x=gc())=='\n' || *x==' '||*x=='\r');
        if(*x==EOF)return 0;
        while(!(*x=='\n'||*x==' '||*x=='\r'||*x==EOF))*(++x)=gc();
        *x=0;
        return 1;
    }
    template<typename A,typename ...B>
    inline bool read(A &x,B &...y){
        return read(x)&&read(y...);
    }
    template<typename A>
    inline bool write (A x) {
        if (!x) putc ('0'); if (x < 0) putc ('-'), x = -x;
        while (x) qu[++ qr] = x % 10 + '0',  x /= 10;
        while (qr) putc (qu[qr --]);
        return 0;
    }
    inline bool write (char x) {
        putc(x);
        return 0;
    }
    inline bool write(const char *x){
        while(*x){putc(*x);++x;}
        return 0;
    }
    inline bool write(char *x){
        while(*x){putc(*x);++x;}
        return 0;
    }
    template<typename A,typename ...B>
    inline bool write(A x,B ...y){
        return write(x)||write(y...);
    }
    //no need to call flush at the end manually!
    struct Flusher_ {~Flusher_(){flush();}}io_flusher_;
}
using io :: read;
using io :: putc;
using io :: write;
int dis[maxm][maxm];
struct base{
	int def,gold;
}b[maxm];
struct ship{
	int x,att,fuel,pri;
}a[N];
int val[N];
int s,t;
int now[N],dep[N],head[N];
struct edge{
	int v,w,nxt;
}e[maxn];
int ecnt;
void addedge(int u,int v,int w)
{
	e[ecnt]={v,w,head[u]};
	head[u]=ecnt++;
	e[ecnt]={u,0,head[v]};
	head[v]=ecnt++;
}
int bfs()//重新建图，按层次建图
{
    queue<int> q;
    while(!q.empty())
        q.pop();
    for(int i=s;i<=t;i++)
    {
    	dep[i]=-1;
    	now[i]=-1; //now[i]表示i的当前弧
    }
    dep[s] = 0; //dep为层次
    q.push(s);
    now[s]=head[s];
    while(!q.empty()){
        int u = q.front();
        q.pop();
        for(int i=head[u]; i!=-1; i=e[i].nxt){
        	int v=e[i].v;
            if(e[i].w > 0 && dep[v] == -1){//如果可以到达且还没有访问，可以到达的条件是剩余容量大于0，没有访问的条件是当前层数还未知
                dep[v] = dep[u] + 1;
                now[v]=head[v];
                q.push(v);
            }
        }
    }
    return dep[t] != -1;
}
int dfs(int u, int mi)//查找路径上的最小流量
{
    if(mi==0||u == t)
        return mi;
    int tmp,sum=0;
    for(int i=now[u]; i!=-1&&mi; i=e[i].nxt){
    	now[u]=i; //当前弧优化
    	int v=e[i].v;
        if(e[i].w > 0 && dep[v] == dep[u] + 1){
			tmp = dfs(v, min(mi, e[i].w));
            e[i].w -= tmp;
            e[i^1].w += tmp;
            sum+=tmp; //一次增广跑多条路，sum为流量总和
            mi-=tmp; //用掉了tmp
            if(!mi) break;
        }
    }
    return sum;
}
ll dinic()
{
    ll ans = 0;
    while(bfs()){
        ans+=dfs(s,inf);
    }
    return ans;
}
int main()
{
	memset(head,-1,sizeof(head));
	memset(dis,0x3f,sizeof(dis));
	int n,m;
	read(n,m);
	for(int i=1;i<=m;i++)
	{
		int u,v;
		read(u,v);
		dis[u][v]=dis[v][u]=1;
	}
	for(int k=1;k<=n;k++)
		for(int i=1;i<=n;i++)
			for(int j=1;j<=n;j++)
				dis[i][j]=min(dis[i][k]+dis[k][j],dis[i][j]);
	int snum,bnum,k;
	read(snum,bnum,k);
	//assert(bnum<=n);
	for(int i=1;i<=snum;i++)
	{
		int x,att,fu,pri;
		read(x,att,fu,pri);
		a[i]={x,att,fu,pri};
	}
	for(int i=1;i<=bnum;i++)
	{
		int x,def,gol;
		read(x,def,gol);
		b[x]={def,gol};
	}
	for(int i=1;i<=snum;i++) val[i]=-inf;
	for(int i=1;i<=snum;i++)
	{
		for(int j=1;j<=n;j++)
		{
			if(a[i].fuel>=dis[a[i].x][j]&&a[i].att>=b[j].def) val[i]=max(val[i],b[j].gold-a[i].pri);
		}
	}
	s=0,t=snum+1;
	for(int i=1;i<=k;i++)
	{
		int u,v;
		read(u,v);
		addedge(v,u,inf);
	}
	ll tot=0;
	for(int i=1;i<=snum;i++)
	{
		//printf("val[%d]=%d\n",i,val[i]);
		if(val[i]<=-inf) continue;
		if(val[i]>=0)
		{
			tot+=val[i];
			addedge(i,t,val[i]);
		}
		if(val[i]<0) addedge(s,i,-val[i]);
	}
	tot-=dinic();
	printf("%lld\n",tot);
	return 0;
}

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    ll n, m;
    cin >> n >> m;
    vector<vector<ll>> dist((size_t) n, vector<ll>((size_t) n, (ll) 1e16));
    for (ll i = 0; i < n; i++) {
        dist[i][i] = (ll) 0;
    }
    for (ll i = 0; i < m; i++) {
        ll u, v;
        cin >> u >> v;
        u--, v--;
        dist[u][v] = dist[v][u] = 0;
    }
    for (ll k = 0; k < n; k++) {
        for (ll i = 0; i < n; i++) {
            for (ll j = 0; j < n; j++) {
                dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
            }
        }
    }
    ll s, b, k;
    cin >> s >> b >> k;
    vector<tuple<ll, ll, ll, ll>> x((size_t) s);
    for (ll i = 0; i < s; i++) {
        cin >> get<0>(x[i]) >> get<1>(x[i]) >> get<2>(x[i]) >> get<3>(x[i]);
        get<0>(x[i])--;
    }
    vector<tuple<ll, ll, ll>> y((size_t) b);
    for (ll i = 0; i < b; i++) {
        cin >> get<0>(y[i]) >> get<1>(y[i]) >> get<2>(y[i]);
        get<0>(y[i])--;
    }
    vector<map<ll, ll>> bases((size_t) n);
    for (ll i = 0; i < b; i++) {
        bases[get<0>(y[i])][get<1>(y[i])] = get<2>(y[i]);
    }
    for (ll i = 0; i < n; i++) {
        for (auto j = bases[i].begin(); j != bases[i].end();) {
            if (j == bases[i].begin() || j->second > prev(j)->second) {
                j++;
            } else {
                j = bases[i].erase(j);
            }
        }
    }
    vector<ll> damages((size_t) s, (ll) -1e16);
    for (ll i = 0; i < s; i++) {
        for (ll j = 0; j < n; j++) {
            if (get<2>(x[i]) >= dist[get<0>(x[i])][j]) {
                auto it = bases[j].upper_bound(get<1>(x[i]));
                if (it != bases[j].begin()) {
                    damages[i] = max(damages[i], prev(it)->second - get<3>(x[i]));
                }
            }
        }
    }
    vector<vector<ll>> init_adj((size_t) s), init_adj_rev((size_t) s);
    vector<vector<pair<ll, ll>>> adj((size_t) s + 2);
    vector<map<ll, ll>> flows((size_t) s + 2);
    auto add_edge = [&](ll u, ll v, ll w) {
        adj[u].emplace_back(v, w);
        adj[v].emplace_back(u, 0);
        flows[u][v] = 0;
        flows[v][u] = 0;
    };
    for (ll i = 0; i < k; i++) {
        ll u, v;
        cin >> u >> v;
        u--, v--;
        if (u != v) {
            init_adj[u].push_back(v);
            init_adj_rev[v].push_back(u);
            add_edge(u, v, (ll) 1e16);
        }
    }
    ll o = 0;
    for (ll u = 0; u < s; u++) {
        if (damages[u] > 0) {
            if (!init_adj[u].empty()) {
                add_edge(s, u, damages[u]);
            } else {
                o += damages[u];
            }
        } else {
            if (!init_adj_rev[u].empty()) {
                add_edge(u, s + 1, -damages[u]);
            }
        }
    }
    vector<bool> visited;
    vector<ll> path;
    function<ll(ll)> visit = [&](ll u) {
        if (!visited[u]) {
            visited[u] = true;
            path.push_back(u);
            if (u == s + 1) {
                return (ll) 1e24;
            } else {
                for (auto[v, w] : adj[u]) {
                    if (w - flows[u][v] > 0) {
                        ll a = visit(v);
                        if (a > 0) {
                            return min(w - flows[u][v], a);
                        }
                    }
                }
            }
            path.pop_back();
        }
        return (ll) 0;
    };
    while (true) {
        visited.assign((ll) s + 2, false);
        path.clear();
        ll a = visit(s);
        if (a > 0) {
            for (ll i = 1; i < (ll) path.size(); i++) {
                flows[path[i - 1]][path[i]] += a;
                flows[path[i]][path[i - 1]] -= a;
            }
            o += a;
        } else {
            break;
        }
    }
    cout << o << endl;
    return 0;
}

#include <iostream>
#include <algorithm>
#include <vector>
#include <map>

#define X first
#define Y second

using namespace std;

const int maxn = 2020;
const int inf = 1e9 + 7;

struct edge {
	int a, b, cap, flow;
	edge(int a, int b, int cap) : a(a), b(b), cap(cap), flow(0) {}
};

int S = 0, T, dist[maxn], q[maxn], ptr[maxn];
vector<edge> e;
vector<int> g[maxn];

void add_edge(int a, int b, int cap) {
	g[a].push_back((int)e.size());
	e.push_back(edge(a, b, cap));
	g[b].push_back((int)e.size());
	e.push_back(edge(b, a, 0));
}

bool bfs() {
	fill(dist, dist + maxn, -1);
	dist[S] = 0;
	int qh = 0, qt = 0;
	q[qt++] = S;
	while(qh < qt and dist[T] == -1) {
		int v = q[qh++];
		for(int id : g[v]) {
			if(dist[e[id].b] == -1 and e[id].flow < e[id].cap) {
				q[qt++] = e[id].b;
				dist[e[id].b] = dist[v] + 1;
			}
		}
	}
	return dist[T] != -1;
}

int dfs(int v, int flow) {
	if(flow == 0) return 0;
	if(v == T) return flow;
	for(; ptr[v] < g[v].size(); ptr[v]++) {
		int id = g[v][ptr[v]];
		if(dist[e[id].b] != dist[v] + 1) continue;
		int pushed = dfs(e[id].b, min(flow, e[id].cap - e[id].flow));
		if(pushed) {
			e[id].flow += pushed;
			e[id ^ 1].flow -= pushed;
			return pushed;
		}
	}
	return 0;
}

long long dinic() {
	long long flow = 0;
	while(bfs()) {
		fill(ptr, ptr + maxn, 0);
		while(int pushed = dfs(S, inf)) flow += pushed;
	}
	return flow;
}

int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	int n, m;
	cin >> n >> m;
	int d[n + 1][n + 1];
	for(int i = 1; i <= n; i++) {
		for(int j = 1; j <= n; j++) {
			d[i][j] = d[j][i] = inf;
		}
		d[i][i] = 0;
	}
	for(int i = 0; i < m; i++) {
		int u, v;
		cin >> u >> v;
		if(u != v) {
			d[u][v] = d[v][u] = 1;
		}
	}
	for(int k = 1; k <= n; k++) {
		for(int i = 1; i <= n; i++) {
			for(int j = 1; j <= n; j++) {
				d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
			}
		}
	}
	int s, b, k;
	cin >> s >> b >> k;
	long long spos[s], attack[s], fuel[s], price[s];
	long long bpos[b], defense[b], gold[b];
	for(int i = 0; i < s; i++) {
		cin >> spos[i] >> attack[i] >> fuel[i] >> price[i];
	}
	for(int i = 0; i < b; i++) {
		cin >> bpos[i] >> defense[i] >> gold[i];
	}
	bool indep[s] = {0};
	pair<int, int> dep[k];
	for(int i = 0; i < k; i++) {
		cin >> dep[i].X >> dep[i].Y;
		indep[dep[i].X - 1] = indep[dep[i].Y - 1] = true;
	}
	vector<pair<long long, long long> > maxpref[n + 1];
	for(int i = 1; i <= n; i++) {
		maxpref[i].push_back({0, -2 * inf});
	}
	for(int i = 0; i < b; i++) {
		maxpref[bpos[i]].push_back({defense[i], gold[i]});
	}
	for(int i = 1; i <= n; i++) {
		sort(maxpref[i].begin(), maxpref[i].end());
		for(int j = 1; j < maxpref[i].size(); j++) {
			maxpref[i][j].Y = max(maxpref[i][j].Y, maxpref[i][j - 1].Y);
		}
	}
	long long maxprofit[s];
	for(int i = 0; i < s; i++) {
		long long ans = -inf * 2;
		for(int j = 1; j <= n; j++) {
			if(d[spos[i]][j] <= fuel[i]) {
				int x = upper_bound(maxpref[j].begin(), maxpref[j].end(), make_pair(attack[i], 0ll)) - maxpref[j].begin();
				ans = max(ans, 1ll * maxpref[j][x - 1].Y - price[i]);
			}
		}
		maxprofit[i] = ans;
	}
	int nxt = 1;
	int newnum[s];
	for(int i = 0; i < s; i++) {
		if(indep[i]) newnum[i] = nxt++;
	}
	T = nxt;
	for(int i = 0; i < s; i++) {
		if(indep[i]) {
			if(maxprofit[i] > 0) add_edge(S, newnum[i], maxprofit[i]);
			else if(maxprofit[i] != -inf * 2) add_edge(newnum[i], T, -maxprofit[i]);
		}
	}
	for(int i = 0; i < k; i++) {
		add_edge(newnum[dep[i].X - 1], newnum[dep[i].Y - 1], 2 * inf);
	}
	long long ans = 0;
	for(int i = 0; i < s; i++) {
		if(maxprofit[i] > 0) ans += maxprofit[i];
	}
	cout << ans - dinic() << '\n';
	return 0;
}

#include <bits/stdc++.h>
//
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 100015;
const int maxm = 1000005;
int g[105][105];
int num[maxn];
int cnt;
void floyed(int n){
    for(int k = 1; k <= n; k++){
        for(int i = 1; i <= n; i++){
            for(int j = 1; j <= n; j++){
                g[i][j] = min(g[i][j], g[i][k]+g[k][j]);
            }
        }
    }
};
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
    while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
struct Edge{
    int to,next,cap,flow;
}edge[maxm];
int tol,head[maxn];
void init()
{
    tol=2;
    memset(head,-1,sizeof(head));
}
void addedge(int u,int v,int w,int rw=0)
{
    edge[tol].to=v;edge[tol].cap=w;edge[tol].flow=0;
    edge[tol].next=head[u];head[u]=tol++;
    edge[tol].to=u;edge[tol].cap=rw;edge[tol].flow=0;
    edge[tol].next=head[v];head[v]=tol++;
}
int Q[maxn];
int dep[maxn],cur[maxn],sta[maxn];
bool bfs(int s,int t,int n)
{
    int front=0,tail=0;
    memset(dep,-1,sizeof(dep[0])*(n+1));
    dep[s]=0;
    Q[tail++]=s;
    while(front<tail){
        int u=Q[front++];
        for(int i=head[u];i!=-1;i=edge[i].next){
            int v=edge[i].to;
            if(edge[i].cap>edge[i].flow&&dep[v]==-1){
                dep[v]=dep[u]+1;
                if(v==t){
                    return true;
                }
                Q[tail++]=v;
            }
        }
    }
    return false;
}
long long dinic(int s,int t,int n)
{
    long long maxflow=0;
    while(bfs(s,t,n)){
        for(int i=0;i<n;i++){
            cur[i]=head[i];
        }
        int u=s,tail=0;
        while(cur[s]!=-1){
            if(u==t){
                int tp=INF;
                for(int i=tail-1;i>=0;i--){
                    tp=min(tp,edge[sta[i]].cap-edge[sta[i]].flow);
                }
                maxflow+=tp;
                for(int i=tail-1;i>=0;i--){
                    edge[sta[i]].flow+=tp;
                    edge[sta[i]^1].flow-=tp;
                    if(edge[sta[i]].cap-edge[sta[i]].flow==0){
                        tail=i;
                    }
                }
                u=edge[sta[tail]^1].to;
            }else if(cur[u]!=-1&&edge[cur[u]].cap>edge[cur[u]].flow&&dep[u]+1==dep[edge[cur[u]].to]){
                sta[tail++]=cur[u];
                u=edge[cur[u]].to;
            }else{
                while(u!=s&&cur[u]==-1){
                    u=edge[sta[--tail]^1].to;
                }
                cur[u]=edge[cur[u]].next;
            }
        }
    }
    return maxflow;
}
//vector<int>fuck[100005];
int fuckacm[100005];
int ps[105];
int in[maxn], out[maxn], shipos[maxn], atk[maxn], f[maxn], p[maxn], baspos[maxn], d[maxn], gold[maxn], val[maxn];
bool svis[maxn];
#define pii pair<int,int>
vector<pii> v1[105];
int main(){
    int n, m, u, v, s, b, k;
    n = read(), m = read();
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n; j++){
            if(i==j) g[i][j] = 0;
            else g[i][j] = g[j][i] = INF;
        }
    }
    for(int i = 1; i <= m; i++){
        u = read(), v = read();
        g[u][v] = g[v][u] = 1;
    }
    floyed(n);
    s = read(), b = read(), k = read();
    for(int i = 1; i <= s; i++){
        shipos[i] = read(), atk[i] = read(), f[i] = read(), p[i] = read();
    }
    for(int i = 1; i <= b; i++){
        baspos[i] = read(), d[i] = read(), gold[i] = read();
        v1[baspos[i]].emplace_back(pii(d[i], gold[i]));
    }
    for(int i = 1; i <= k; i++){
        int tmp1, tmp2;
        tmp1 = read(), tmp2 = read();
        fuckacm[tmp1] = tmp2;
        in[tmp2]++, out[tmp1]++;
    }
    for(int i = 1; i <= n; i++){
        sort(v1[i].begin(), v1[i].end()); ps[i] = 0;
        for(int j = 1; j < v1[i].size(); j++){
            v1[i][j].second = max(v1[i][j].second, v1[i][j-1].second);
        }
    }
    for(int i = 1; i <= s; i++){
        int ma = 0;
        for(int j = 1; j <= n; j++){
            if(g[shipos[i]][j] <= f[i]){
                if(v1[j].empty()) continue;
                while(ps[j] < v1[j].size()-1 && v1[j][ps[j]+1].first <= atk[i]) ps[j]++;
                if(v1[j][ps[j]].first <= atk[i]) ma = max(ma, v1[j][ps[j]].second);
            }
        }
        val[i] = ma-p[i];
    }
    long long ans = 0;
    for(int i = 1; i <= s; i++){
        if(in[i] == 0 && out[i] > 0 && !svis[i]){
            if(val[i] <= 0){
                svis[i] = true;
            }
        }
        if(in[i] == 0 && out[i] == 0 && val[i]>0 && !svis[i]){
            ans += val[i];
            svis[i] = true;
        }
        if(in[i] == 0 && out[i] == 0 && val[i] < 0 && !svis[i]){
            svis[i] = true;
        }
    }
    int S = 2015+1, T = S+1;
    init();
    for(int i = 1; i <= s; i++){
        if(!svis[i]){
            if(val[i] > 0){
                num[i] = ++cnt;
                addedge(S, cnt, val[i]);
                ans += val[i];
            }
            else{
                num[i] = ++cnt;
                addedge(cnt, T, -val[i]);
            }
        }
    }
    for(int i = 1; i <= s; i++){
        if(!svis[i] && val[i] > 0)
            addedge(num[i], num[fuckacm[i]], INF);
    }
    ans -= dinic(S, T, T+1);
    cout << ans;
    return 0;
}

#include<bits/stdc++.h>

using namespace std;

#define double long double

typedef pair<int,int> ii;
typedef pair<int,long long> il;
typedef pair<long long,long long> ll;
typedef pair<ll,int> lli;
typedef pair<long long,int> li;
typedef pair<double,double> dd;
typedef pair<ii,int> iii;
typedef pair<double,int> di;
typedef pair<int,ii> iii2;
typedef pair<ii,ii> iiii;
typedef vector<int> vi;
long long mod = 1000000007LL;
long long large = 2000000000000000000LL;

struct Edge {
	int from,to;
	long long cap,flow;
};

struct Dinic {
	int n,m,s,t;
	vector<Edge> edges;
	vector<vector<int> > G;
	vector<bool> vis;
	vector<int> dis;
	vector<int> cur;
	void init(int maxn){
		edges.clear();
		G.assign(maxn+10,vector<int>(0));
		vis.assign(maxn+10,false);
		dis.assign(maxn+10,0);
		cur.assign(maxn+10,0);
		n=maxn;
	}
	void addEdge(int from,int to,long long cap){
		edges.push_back((Edge){from,to,cap,0});
		edges.push_back((Edge){to,from,0,0});
		m=edges.size();
		G[from].push_back(m-2);
		G[to].push_back(m-1);
	}
	bool BFS() {
		vis.assign(n+10,false);
		queue<int> q;
		q.push(s);
		dis[s]=0;
		vis[s]=true;
		while(!q.empty()){
			int u=q.front();
			q.pop();
			for(int i=0;i<(int)G[u].size();i++){
				Edge& e=edges[G[u][i]];
				if(!vis[e.to]&&e.cap>e.flow){
					vis[e.to]=1;
					dis[e.to]=dis[u]+1;
					q.push(e.to);
				}
			}
		}
		return vis[t];
	}
	long long DFS(int x,long long a){
		if(x==t||a==0) return a;
		long long flow=0,f;
		for(int& i=cur[x];i<(int)G[x].size();i++){
			Edge& e=edges[G[x][i]];
			if(dis[x]+1==dis[e.to]&&(f=DFS(e.to,min(a,e.cap-e.flow)))>0){
				e.flow+=f;
				edges[G[x][i]^1].flow-=f;
				flow+=f;
				a-=f;
				if(a==0) break;
			}
		}
		return flow;
	}
	long long maxflow(int s,int t){
		this->s=s;
		this->t=t;
		long long flow=0;
		while(BFS()){
			cur.assign(n+10,0);
			flow+=DFS(s,large);
		}
		return flow;
	}
	void clearflow(){
		vis.assign(n+10,false);
		dis.assign(n+10,0);
		cur.assign(n+10,0);
		for(int i=0;i<(int)edges.size();i++){
			edges[i].flow=0;
		}
	}
};

int main(){

	int n,m;
	cin>>n>>m;
	vector<vector<int> > g(n,vector<int>(n,1000000000));
	for(int i=0;i<m;i++){
		int x,y;
		cin>>x>>y;
		x--;y--;
		g[x][y] = g[y][x] =1;
	}

	for(int i=0;i<n;i++) g[i][i] = 0;
	for(int k=0;k<n;k++) for(int i=0;i<n;i++) for(int j=0;j<n;j++) g[i][j] = min(g[i][j],g[i][k]+g[k][j]);

	int s,b;
	cin>>s>>b;

	int k;
	cin>>k;

	vector<int> ps(s,0),a(s,0),f(s,0),p(s,0);
	vector<int> pb(b,0),d(b,0),gold(b,0);
	for(int i=0;i<s;i++){
		cin>>ps[i]>>a[i]>>f[i]>>p[i];
		ps[i]--;
	}
	for(int i=0;i<b;i++){
		cin>>pb[i]>>d[i]>>gold[i];
		pb[i]--;
	}

	vector<vector<ii> > adj(n,vector<ii>());
	for(int i=0;i<b;i++){
		adj[pb[i]].push_back(ii(d[i],gold[i]));
	}
	for(int i=0;i<n;i++) sort(adj[i].begin(),adj[i].end());
	for(int i=0;i<n;i++){
		for(int j=0;j<(int)adj[i].size();j++){
			if(j) adj[i][j].second = max(adj[i][j].second,adj[i][j-1].second);
		}
	}

	for(int i=0;i<s;i++){
		int ans = 0;
		for(int j=0;j<n;j++){
			if(g[ps[i]][j]>f[i]) continue;
			int pt = upper_bound(adj[j].begin(),adj[j].end(),ii(a[i],1000000010))-adj[j].begin();
			pt--;
			if(pt>=0) ans = max(ans,adj[j][pt].second);
		}
		p[i] = ans-p[i];
	}

	Dinic din;
	din.init(s+10);
	int st = s;
	int en = st+1;
	long long sum = 0;
	for(int i=0;i<s;i++){
		if(p[i]>0){
			din.addEdge(st,i,p[i]);
			sum+=p[i];
		}else din.addEdge(i,en,-p[i]);
	}

	for(int i=0;i<k;i++){
		int x,y;
		cin>>x>>y;
		x--;y--;
		din.addEdge(x,y,large);
	}

	cout<<sum-din.maxflow(st,en)<<endl;

    return 0;
}

#pragma GCC optimize("O3")
#include <bits/stdc++.h>

using namespace std;

#define sim template<class c
#define ris return *this
#define dor > debug & operator<<
#define eni(x) sim>typename \
  enable_if<sizeof dud<c>(0) x 1, debug&>::type operator<<(c i) {
sim> struct rge { c b, e; };
sim> rge<c> range(c i, c j) { return rge<c>{i, j}; }
sim> auto dud(c*x) -> decltype(cerr<<*x, 0);
sim> char dud(...);
struct debug {
#ifdef LOCAL
~debug() { cerr << endl; }
eni(!=) cerr << boolalpha << i; ris; }
eni(==) ris << range(begin(i), end(i)); }
sim, class b dor (pair<b,c> d) {
  ris<<"("<<d.first<<", "<<d.second<<")";
}
sim dor(rge<c> d) {
  *this<<"[";
  for (auto it = d.b; it != d.e; ++it)
    *this << ", " + 2 * (it == d.b) << *it;
  ris <<" ]";
}
#else
sim dor(const c&) { ris; }
#endif
};
#define imie(...) " [" << #__VA_ARGS__ ": " << (__VA_ARGS__) << "] "

using ll = long long;
#define int ll
#define PB push_back
#define MP make_pair
#define PII pair<int, int>
#define SZ(x) ((int)(x).size())
#define VI vector<int>
using pii = pair<int, int>;
using pll = pair<ll, ll>;
using vi = vector<int>;
using vll = vector<ll>;

struct Dinic {
  struct Edge { int v, c, inv; };

public:
  Dinic() : n(-1) {}
  void AddEdge(int a, int b, int cap, int bi_dir) {
    debug() << imie(a) << imie(b) << imie(cap);
    if (n < max(a, b)) { n = max(n, max(a, b)); ResizeVectors(); }
    e_orig[a].PB(Edge{b, cap, SZ(e_orig[b])});
    e_orig[b].PB(Edge{a, bi_dir * cap, SZ(e_orig[a]) - 1});
  }
  int MaxFlow(int s, int t) {
    if (t > n || s > n) { n = max(s, t); ResizeVectors(); }
    e = e_orig; int result = 0;
    while (Bfs(s, t)) {
      fill_n(beg.begin(), n + 1, 0);
      result += Dfs(s, t, kInf);
    }
    return result;
  }

  int n;
  vector<vector<Edge>> e_orig, e;
  VI dis, beg;

  bool Bfs(int s, int t) {
    fill_n(dis.begin(), n + 1, n + 1);
    dis[s] = 0; VI que{s};
    for (int i = 0; i < SZ(que); ++i) {
      int v = que[i];
      for (auto edge : e[v]) {
        int nei = edge.v;
        if (edge.c && dis[nei] > dis[v] + 1) {
          dis[nei] = dis[v] + 1;
          que.PB(nei);
          if (nei == t) { return true; }
        }
      }
    }
    return false;
  }

  int Dfs(int v, int t, int min_cap) {
    int result = 0;
    if (v == t || !min_cap) { return min_cap; }
    for (int &i = beg[v]; i < SZ(e[v]); ++i) {
      int nei = e[v][i].v, c = e[v][i].c;
      if (dis[nei] == dis[v] + 1 && c > 0) {
        int flow_here = Dfs(nei, t, min(min_cap, c));
        result += flow_here;
        min_cap -= flow_here;
        e[v][i].c -= flow_here;
        e[nei][e[v][i].inv].c += flow_here;
      }
      if (min_cap == 0) { break; }
    }
    return result;
  }

  void ResizeVectors() {
    e_orig.resize(n + 2);
    beg.resize(n + 2);
    dis.resize(n + 2);
  }

  static const int kInf = 1e18;
};

const int MaxN = 105;
const int MaxItems = 1e5 + 100;

int n, m;
vi adj[MaxN];
int s, b, k, h;
int dist[MaxN][MaxN];
vector<pii> at_vert[MaxN];

int sp_loc[MaxItems], sp_atk[MaxItems], sp_fuel[MaxItems], sp_price[MaxItems];
int bs_loc[MaxItems], bs_def[MaxItems], bs_gold[MaxItems];

vi dep_adj[MaxItems];
bool any_dep[MaxItems];
int dep_idx[MaxItems];

int32_t main() {
  scanf("%lld%lld", &n, &m);
  for (int i = 0; i < n; ++i) {
    for (int j = 0; j < n; ++j) {
      dist[i][j] = 1e9;
    }
    dist[i][i] = 0;
  }

  for (int i = 0; i < m; ++i) {
    int u, v;
    scanf("%lld%lld", &u, &v);
    adj[u].push_back(v);
    adj[v].push_back(u);
    dist[u][v] = dist[v][u] = 1;
  }

  for (int k = 1; k <= n; ++k) {
    for (int i = 1; i <= n; ++i) {
      for (int j = 1; j <= n; ++j) {
        dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
      }
    }
  }

  scanf("%lld%lld%lld", &s, &b, &k);

  for (int i = 0; i < s; ++i) {
    scanf("%lld%lld%lld%lld", &sp_loc[i], &sp_atk[i], &sp_fuel[i], &sp_price[i]);
  }
  for (int i = 0; i < b; ++i) {
    scanf("%lld%lld%lld", &bs_loc[i], &bs_def[i], &bs_gold[i]);
    at_vert[bs_loc[i]].emplace_back(bs_def[i], bs_gold[i]);
  }

  for (int v = 1; v <= n; ++v) {
    auto &X = at_vert[v];
    sort(X.begin(), X.end());

    const int sz = X.size();
    int cur_max = -1;
    int ptr = 0;
    for (int i = 0; i < sz; ++i) {
      if (X[i].second <= cur_max) { continue; }
      X[ptr++] = X[i];
      cur_max = X[i].second;
    }
    X.resize(ptr);

    debug() << imie(v) << imie(X);
  }

  const int kSmallInf = 2e9;
  const ll kLargeInf = 2e14;

  vll sp_best(s, -kLargeInf);
  for (int i = 0; i < s; ++i) {
    for (int v = 1; v <= n; ++v) {
      if (sp_fuel[i] < dist[sp_loc[i]][v]) { continue; }
      const int atk = sp_atk[i];
      auto iter =
        lower_bound(at_vert[v].begin(), at_vert[v].end(),
                    pii(atk, kSmallInf));
      if (iter == at_vert[v].begin()) {
        continue;
      } else {
        int bnd = prev(iter)->second;
        sp_best[i] = max(sp_best[i], (ll)bnd - sp_price[i]);
      }
    }
    debug() << imie(i) << imie(sp_best[i]);
  }

  for (int i = 0; i < k; ++i) {
    int u, v;
    scanf("%lld%lld", &u, &v);
    --u; --v;
    any_dep[u] = any_dep[v] = true;
    dep_adj[u].PB(v);
  }

  ll ans = 0;
  int curidx = 0;
  for (int i = 0; i < s; ++i) {
    if (!any_dep[i] && sp_best[i] >= 0) {
      ans += sp_best[i];
    }
    if (any_dep[i]) {
      dep_idx[i] = curidx++;
    }
  }

  Dinic dinic;
  const int source = curidx;
  const int sink = source + 1;

  for (int i = 0; i < s; ++i) {
    if (!any_dep[i]) { continue; }
    if (sp_best[i] >= 0) {
      dinic.AddEdge(source, dep_idx[i], sp_best[i], 0);
      ans += sp_best[i];
    } else {
      dinic.AddEdge(dep_idx[i], sink, -sp_best[i], 0);
    }

    for (int j : dep_adj[i]) {
      dinic.AddEdge(dep_idx[i], dep_idx[j], kLargeInf, 0);
    }
  }

  const ll flow = dinic.MaxFlow(source, sink);
  ans -= flow;

  printf("%lld\n", ans);

}

#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <utility>
#include <limits>

struct base_t {
    int64_t position, defense, gold;
    friend std::istream& operator >> (std::istream& flux, base_t& b) {
        flux >> b.position >> b.defense >> b.gold;
        return flux;
    }
    bool operator < (const base_t& b) const {
        return this->defense < b.defense;
    }
};

struct ship_t {
    int64_t position, strength, fuel, price;
    friend std::istream& operator >> (std::istream& flux, ship_t& s) {
        flux >> s.position >> s.strength >> s.fuel >> s.price;
        return flux;
    }
};

struct Flow_Edge {
    int from, to;
    int64_t capacity, flow = 0LL;
    Flow_Edge (const int& from, const int& to, const int64_t& capacity): from (from), to (to), capacity (capacity) {
    }
};

constexpr auto Inf = std::numeric_limits <int64_t>::max ();
using Ip = std::pair <int64_t, int64_t>;
using Vi = std::vector <int>;
using VVi = std::vector <Vi>;
using Vi64 = std::vector <int64_t>;
using VVi64 = std::vector <Vi64>;
using VIp = std::vector <Ip>;
using VVIp = std::vector <VIp>;
using Vf = std::vector <Flow_Edge>;
using Vs = std::vector <ship_t>;
using Vb = std::vector <base_t>;
using Qi = std::queue <int>;

struct Dinic {
    Vf Edges;
    VVi Adj;
    int n, s, t;
    Vi Level, Ptr;
    Qi Q;
    Dinic (const int& n, const int& s, const int& t): n (n), s (s), t (t) {
        Adj.resize (n), Level.resize (n), Ptr.resize (n);
    }
    void add_edge (const int& u, const int& v, const int64_t& cap) {
        if (u == v) return;
        Edges.emplace_back (u, v, cap);
        Adj[u].emplace_back (Edges.size () - 1);
        Edges.emplace_back (v, u, 0);
        Adj[v].emplace_back (Edges.size () - 1);
    }
    bool bfs () {
        while (!Q.empty ()) {
            int v = Q.front (); Q.pop ();
            for (const auto& id: Adj[v]) {
                if (Edges[id].capacity - Edges[id].flow < 1)
                    continue;
                if (Level[Edges[id].to] != -1)
                    continue;
                Level[Edges[id].to] = Level[v] + 1;
                Q.push (Edges[id].to);
            }
        }
        return Level[t] != -1;
    }
    int64_t dfs (const int& v, const int64_t& pushed) {
        if (!pushed)
            return 0LL;
        if (v == t)
            return pushed;
        for (int& cid = Ptr[v]; cid < (int)Adj[v].size (); ++ cid) {
            int id = Adj[v][cid], u = Edges[id].to;
            if (Level[v] + 1 != Level[u] || Edges[id].capacity - Edges[id].flow < 1)
                continue;
            int64_t transport = dfs (u, std::min (pushed, Edges[id].capacity - Edges[id].flow));
            if (!transport)
                continue;
            Edges[id].flow += transport;
            Edges[id ^ 1].flow -= transport;
            return transport;
        }
        return 0LL;
    }
    int64_t max_flow () {
        int64_t f = 0LL;
        while (true) {
            std::fill (Level.begin (), Level.end (), -1);
            Level[s] = 0;
            Q.push (s);
            if (!bfs ())
                break;
            std::fill (Ptr.begin (), Ptr.end (), 0);
            while (int64_t pushed = dfs (s, Inf))
                f += pushed;
        }
        return f;
    }
};

int n, m, u, v, s, b, k;
Vi64 Value;
VVi64 Cost;
Vs Ships;
Vb Bases;
VVIp Bases_at;

int main () {
    std::ios_base::sync_with_stdio (false), std::cin.tie (nullptr), std::cout.tie (nullptr);
    std::cin >> n >> m;
    Cost.assign (n + 1, Vi64 (n + 1, Inf));
    for (int i = 1; i <= n; ++ i) Cost[i][i] = 0LL;
    for (int i = 1; i <= m; ++ i)
        std::cin >> u >> v, Cost[u][v] = Cost[v][u] = std::min (Cost[u][v], 1LL);

    for (int k = 1; k <= n; ++ k)
        for (int i = 1; i <= n; ++ i)
            for (int j = 1; j <= n; ++ j)
                Cost[i][j] = std::min (Cost[i][j], Cost[i][k] + Cost[k][j]);

    std::cin >> s >> b >> k;
    Value.resize (s + 1), Bases_at.resize (n + 1);
    Ships.resize (s + 1), Bases.resize (b + 1);
    for (int i = 1; i <= s; ++ i)
        std::cin >> Ships[i];
    for (int i = 1; i <= b; ++ i)
        std::cin >> Bases[i];

    std::sort (Bases.begin (), Bases.end ());
    for (int i = 1; i <= b; ++ i) {
        int pos = Bases[i].position;
        if (Bases_at[pos].empty () || Bases_at[pos].back ().second < Bases[i].gold)
            Bases_at[pos].emplace_back (Bases[i].defense, Bases[i].gold);
    }

    int source = 0, sink = s + 1;
    Dinic dinic (s + 2, source, sink);
    int64_t ans = 0LL;
    for (int i = 1; i <= s; ++ i) {
        bool found = false;
        for (int p = 1; p <= n; ++ p) {
            if (Cost[Ships[i].position][p] > Ships[i].fuel)
                continue;
            auto it = std::upper_bound (Bases_at[p].begin (), Bases_at[p].end (), std::make_pair (Ships[i].strength, Inf));
            if (it != Bases_at[p].begin ())
                -- it, found = true, Value[i] = std::max (Value[i], it->second);
        }
        Value[i] -= Ships[i].price;
        if (!found)
            Value[i] = -Inf;
        if (Value[i] >= 0)
            ans += Value[i], dinic.add_edge (source, i, Value[i]);
        else
            dinic.add_edge (i, sink, -Value[i]);
    }

    for (int i = 1; i <= k; ++ i)
        std::cin >> u >> v,
        dinic.add_edge (u, v, Inf);

    std::cout << ans - dinic.max_flow ();

    return 0;
}

#include <bits/stdc++.h>
#define db(x) cout << (x) << '\n';
using namespace std;
typedef long long ll;
typedef pair<ll,ll> pii;
#define MAXN 105
#define oo2 ((ll)(1e9+7))
#define MAXM 100005

ll d[MAXN][MAXN];
vector<pii> bs[MAXN];
ll mbs[MAXN][MAXM],pl[MAXM],pp[MAXM][4];

template<typename flow_type>
struct dinic
{
	struct edge
	{
		size_t src, dst, rev;
		flow_type flow, cap;
	};

	int n;
	vector<vector<edge>> adj;

	dinic(int n) : n(n), adj(n), level(n), q(n), it(n) {}

	void add_edge(size_t src, size_t dst, flow_type cap, flow_type rcap = 0)
	{
		adj[src].push_back({src, dst, adj[dst].size(), 0, cap});
		if (src == dst) adj[src].back().rev++;
		adj[dst].push_back({dst, src, adj[src].size() - 1, 0, rcap});
	}

	vector<int> level, q, it;

	bool bfs(int source, int sink)
	{
		fill(level.begin(), level.end(), -1);
		for (int qf = level[q[0] = sink] = 0, qb = 1; qf < qb; ++qf)
		{
			sink = q[qf];
			for (edge &e : adj[sink])
			{
				edge &r = adj[e.dst][e.rev];
				if (r.flow < r.cap && level[e.dst] == -1)
					level[q[qb++] = e.dst] = 1 + level[sink];
			}
		}
		return level[source] != -1;
	}

	flow_type augment(int source, int sink, flow_type flow)
	{
		if (source == sink) return flow;
		for (; it[source] != adj[source].size(); ++it[source])
		{
			edge &e = adj[source][it[source]];
			if (e.flow < e.cap && level[e.dst] + 1 == level[source])
			{
				flow_type delta = augment(e.dst, sink,
								  min(flow, e.cap - e.flow));
				if (delta > 0)
				{
					e.flow += delta;
					adj[e.dst][e.rev].flow -= delta;
					return delta;
				}
			}
		}
		return 0;
	}

	flow_type max_flow(int source, int sink)
	{
		for (int u = 0; u < n; ++u)
			for (edge &e : adj[u]) e.flow = 0;
		flow_type flow = 0;
		flow_type oo = numeric_limits<flow_type>::max();

		while (bfs(source, sink))
		{
			fill(it.begin(), it.end(), 0);
			for (flow_type f; (f = augment(source, sink, oo)) > 0;)
				flow += f;

		} // level[u] = -1 => source side of min cut
		return flow;
	}
};

int main()
{
    ios_base::sync_with_stdio(0);
    cin.tie(0);

    ll n,m,u,v;
    cin >> n >> m;
    for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
            d[i][j]=oo2;
    for(ll i=0;i<m;i++)
    {
        cin >> u >> v;
        u--,v--;
        d[u][v]=d[v][u]=1;
    }

    for(int i=0;i<n;i++)
        d[i][i]=0;
    for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
            for(int k=0;k<n;k++)
                d[j][k]=min(d[j][k],d[j][i]+d[i][k]);

    ll s,b,k,gg,de;
    cin >> s >> b >> k;
    for(ll i=0;i<s;i++)
    {
        cin >> pp[i][0] >> pp[i][1] >> pp[i][2] >> pp[i][3];
        pp[i][0]--;
    }
    for(int i=0;i<b;i++)
    {
        cin >> u >> de >> gg;
        u--;
        bs[u].push_back(pii(de,gg));
    }

    for(int i=0;i<n;i++)
    {
        sort(bs[i].begin(),bs[i].end());
        ll ma=0;
        for(ll j=0;j<bs[i].size();j++)
        {
            ma=max(ma,bs[i][j].second);
            mbs[i][j]=ma;
        }
    }

    dinic<ll> g(2+s);
    ll s1=0;
    for(int i=0;i<s;i++)
    {
        ll ma=0;
        for(int j=0;j<n;j++)
        {
            if(d[j][pp[i][0]]>pp[i][2])
                continue;
            ll pos=lower_bound(bs[j].begin(),bs[j].end(),pii(pp[i][1],oo2))-bs[j].begin();
            if(pos)
                ma=max(ma,mbs[j][pos-1]);
        }
        pl[i]=ma-pp[i][3];
        if(pl[i]>0)
        {
            g.add_edge(0,i+1,pl[i]);
            s1+=pl[i];
        }
        if(pl[i]<0)
            g.add_edge(i+1,s+1,-pl[i]);
    }

    for(ll i=0;i<k;i++)
    {
        cin >> u >> v;
        g.add_edge(u,v,oo2*oo2);
    }

    db(s1-g.max_flow(0,s+1))

    return 0;
}

#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define ULL unsigned long long
#define mp make_pair
#define pb push_back
#define pii pair<int,int>
#define pll pair<LL,LL>
#define x first
#define y second
#define pi acos(-1)
#define sqr(x) ((x)*(x))
#define pdd pair<double,double>
#define MEMS(x) memset(x,-1,sizeof(x))
#define MEM(x) memset(x,0,sizeof(x))
#define less Less
vector<int> v[100005];
struct Dinic{
    static const int MXN = 250000;
    struct Edge{ int v,f,re; Edge(int a,int b,int c):v(a),f(b),re(c){}};
    int n,s,t,level[MXN];
    vector<Edge> E[MXN];
    void init(int _n, int _s, int _t){
        n = _n; s = _s; t = _t;
        for (int i=0; i<=n; i++) E[i].clear();
    }
    void add_edge(int u, int v, int f){
        E[u].pb(Edge(v,f,E[v].size()));
        E[v].pb(Edge(u,0,E[u].size()-1));//direct
     //   printf("%d %d %d\n",u,v,f);
    }
    bool BFS(){
        MEMS(level);
        queue<int> que;
        que.push(s);
        level[s] = 0;
        while (!que.empty()){
            int u = que.front(); que.pop();
            for (auto it : E[u]){
                if (it.f > 0 && level[it.v] == -1){
                    level[it.v] = level[u]+1;
                    que.push(it.v);
                }
            }
        }
        return level[t] != -1;
    }
    LL DFS(int u, LL nf){
        if (u == t) return nf;
        LL res = 0;
        for (auto &it : E[u]){
            if (it.f > 0 && level[it.v] == level[u]+1){
                LL tf = DFS(it.v, min(nf,(LL)it.f));
                res += tf; nf -= tf; it.f -= tf;
                E[it.v][it.re].f += tf;
                if (nf == 0) return res;
            }
        }
        if (!res) level[u] = -1;
        return res;
    }
    LL flow(LL res=0){
        while ( BFS() )
        res += DFS(s,1e18);
        return res;
    }
}flow;
int vis[100005],s;
void go(int x,int t){
    for(auto it:v[x]){
        if(vis[it]!=t){
            flow.add_edge(t,it+s,2e9);
            vis[it]=t;
            go(it,t);
        }
    }
}
int main(){
    int n,m;
    scanf("%d %d",&n,&m);
    int dis[105][105];
    for(int i = 1;i<=n;i++){
        for(int j = 1;j<=n;j++)
            dis[i][j]=1e9;
        dis[i][i]=0;
    }
    for(int i = 0;i<m;i++){
        int x,y;
        scanf("%d %d",&x,&y);
        dis[x][y]=dis[y][x]=1;
    }
    for(int i = 1;i<=n;i++){
        for(int j = 1;j<=n;j++){
            for(int k = 1;k<=n;k++){
                dis[j][k]=min(dis[j][i]+dis[i][k],dis[j][k]);
            }
        }
    }
    int B,k;
    scanf("%d %d %d",&s,&B,&k);
    int x[100005],a[100005],f[100005],p[100005];
    vector<pii> base[105];
    for(int i = 1;i<=s;i++){
        scanf("%d %d %d %d",&x[i],&a[i],&f[i],&p[i]);
    }
    for(int i = 0;i<B;i++){
        int a,b,c;
        scanf("%d %d %d",&a,&b,&c);
        base[a].pb(mp(b,c));
    }
    for(int i = 1;i<=n;i++){
    //    base[i].pb(mp(0,0));
        sort(base[i].begin(),base[i].end());
        vector<pii> tmp=base[i];
        base[i].clear();
        base[i].pb(mp(0,0));
        for(auto it:tmp){
            if(it.y>base[i].back().y){
                base[i].pb(it);
            }
        }
       // for(auto it:base[i])
       // printf("%d %d ",it.x,it.y);
       // printf("\n");
    }
    int val[100005];
    for(int i = 1;i<=s;i++){
        val[i]=-p[i];
        for(int j = 1;j<=n;j++){
            if(dis[x[i]][j]<=f[i]){
              //  printf("%d %d\n",i,j);
                val[i]=max(val[i],(lower_bound(base[j].begin(),base[j].end(),mp(a[i],1000000000))-1)->y-p[i]);
                //printf("%d\n",(lower_bound(base[i].begin(),base[i].end(),mp(a[i],1000000000))-1)->y)
            }
        }
        //printf("%d\n",val[i]);
    }
    for(int i = 0;i<k;i++){
        int a,b;
        scanf("%d %d",&a,&b);
        v[b].pb(a);
    }
    flow.init(2*s+10,0,2*s+1);
    LL ans=0;
    for(int i =1;i<=s;i++){
        if(val[i]>0){
            ans+=val[i];
            flow.add_edge(i+s,2*s+1,val[i]);
        }
        else{
            flow.add_edge(0,i,-val[i]);
            go(i,i);
        }

    }
  //  printf("%lld\n",ans);
    printf("%lld\n",ans-flow.flow());
}

#include<bits/stdc++.h>
using namespace std;

const int MAXN=3000+5,MAXM=10000+10;
const long long int INF = 1e15;
bool visit[MAXN];
int head[MAXN],dist[MAXN],stamp,tmphead[MAXN];
struct EDGE{
   int to;
   long long int r;
   int next;
}edge[MAXM*2];
void init(){
   stamp=0;
   memset(head,-1,sizeof head);
}
void addedge(int a,int b,long long int c){
   edge[stamp]={b,c,head[a]};
   head[a]=stamp++;
   edge[stamp]={a,0,head[b]};
   head[b]=stamp++;
}
int BFS(int s,int t){
   for(int i=0;i<=t;i++)//The nodes being used
      dist[i]=1e9;
   memset(visit,0,sizeof visit);
   queue<int> q;
   q.push(s);dist[s]=0;visit[s]=true;
   while(!q.empty()){
      int now=q.front();q.pop();
      for(int i=head[now];i!=-1;i=edge[i].next){
         int nextnode=edge[i].to;
         if(edge[i].r>0&&!visit[nextnode]){
            dist[nextnode]=dist[now]+1;
            visit[nextnode]=true;
            q.push(nextnode);
            if(nextnode==t)   return dist[t];
         }
      }
   }
   return -1;
}
long long int DFS(int now,long long int df,int t){
   if(now==t)  return df;
   visit[now]=true;
   for(int i=tmphead[now];i!=-1;tmphead[now]=i=edge[i].next){
      int nextnode=edge[i].to;
      if(edge[i].r>0&&dist[now]+1==dist[nextnode]&&!visit[nextnode]){
         long long int f=DFS(nextnode,min(df,edge[i].r),t);
         if(f){
            edge[i].r-=f;
            edge[i^1].r+=f;
            return f;
         }
      }
   }
   return 0;
}
long long int Dinic(int s,int t){
   long long int flow=0;
   while(BFS(s,t)!=-1){
      memcpy(tmphead,head,sizeof head);
      while(true){
         memset(visit,0,sizeof visit);
         long long int f=DFS(s,INF,t);
         if(!f)   break;
         flow+=f;
      }
   }
   return flow;
}

int dp[101][101];
struct SP{
	int x,a,f,p,pro,idx;
	bool operator<(const SP& rhs)const{
		return a<rhs.a;
	}
}sp[100001];

struct BA{
	int x,d,g;
	bool operator<(const BA& rhs)const{
		return d<rhs.d;
	}
}ba[100001];
int cur[101];
int s1[1001],s2[1001];
map<int,int> mp;
set<int> st;
int main(){
	ios_base::sync_with_stdio(0);
	cin.tie(0);
	int n,m;
	cin>>n>>m;
	init();
	for(int i=1;i<=100;i++)
		cur[i]=-1e9;
	for(int i=1;i<=100;i++)
		for(int j=1;j<=100;j++)
			dp[i][j]=1e9+1;
	for(int i=1,u,v;i<=m;i++){
		cin>>u>>v;
		dp[u][v]=dp[v][u]=1;
	}
	for(int i=1;i<=100;i++)
		dp[i][i]=0;
	for(int k=1;k<=n;k++)
		for(int i=1;i<=n;i++)
			for(int j=1;j<=n;j++)
				dp[i][j]=min(dp[i][j],dp[i][k]+dp[k][j]);
	int s,b,k;
	cin>>s>>b>>k;
	for(int i=1;i<=s;i++){
		cin>>sp[i].x>>sp[i].a>>sp[i].f>>sp[i].p;
		sp[i].pro=-1e9-1;
		sp[i].idx=i;
	}
	sort(sp+1,sp+s+1);
	for(int i=1;i<=b;i++){
		cin>>ba[i].x>>ba[i].d>>ba[i].g;
	}
	sort(ba+1,ba+b+1);
	int pb=1;
	for(int i=1;i<=s;i++){
		while(pb<=b&&ba[pb].d<=sp[i].a)
			cur[ba[pb].x]=max(cur[ba[pb].x],ba[pb].g),pb++;
		for(int j=1;j<=n;j++)
			if(dp[j][sp[i].x]<=sp[i].f)
				sp[i].pro=max(sp[i].pro,cur[j]);
	}
	for(int i=1;i<=k;i++){
		cin>>s1[i]>>s2[i];
		st.insert(s1[i]);st.insert(s2[i]);
	}
	int stp=0;
	for(int it:st)
		mp[it]=++stp;
	long long int ans=0;
	for(int i=1;i<=s;i++){
		sp[i].pro-=sp[i].p;
		if(sp[i].pro>=0)	ans+=sp[i].pro;
		if(mp.find(sp[i].idx)!=mp.end()){
			if(sp[i].pro>0)
				addedge(stp+1,mp[sp[i].idx],sp[i].pro);
			else if(sp[i].pro<0)
					addedge(mp[sp[i].idx],stp+2,(sp[i].pro<-1e9?INF:-sp[i].pro));
		}
	}
	for(int i=1;i<=k;i++)
		addedge(mp[s1[i]],mp[s2[i]],INF);
	cout<<ans-Dinic(stp+1,stp+2)<<endl;
}

#include <iostream>
#include <fstream>
#include <numeric>
#include <iomanip>
#include <cstring>
#include <string>
#include <algorithm>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <deque>

#define sz(a) (int)((a).size())
#define all(a) (a).begin(), (a).end()
#define pb push_back

using namespace std; using ll = long long; using vi = vector<int>; using pii = pair<int, int>; using ld = long double;

const int inf = (int)1e9 + 100;

int n, m;
int d[100][100];
int s, b, k;

struct ship {
	int x, a, f, p;
} ss[100000];

struct base {
	int x, d, g;
} bb[100000];

struct maxflow {
	struct edge {
		int to, c, f;
	};

	vector<edge> e;
	vector<vi> g;
	int N, S, T;
	vi pt, d;
	int A;

	bool bfs() {
		fill_n(d.begin(), N, inf);
		d[S] = 0;
		queue<int> q;
		q.push(S);
		while (!q.empty()) {
			int v = q.front();
			q.pop();
			for (int i : g[v]) {
				edge& ee = e[i];
				if (ee.c - ee.f >= A && d[ee.to] == inf) {
					d[ee.to] = d[v] + 1;
					q.push(ee.to);
				}
			}

		}
		return (d[T] != inf);
	}

	int dfs(int v, int cmin) {
		if (v == T) {
			return cmin;
		}
		for (; pt[v] < sz(g[v]); pt[v]++) {
			int i = g[v][pt[v]];
			edge& ee = e[i];
			if (ee.c - ee.f >= A && d[ee.to] == d[v] + 1) {
				int f = dfs(ee.to, min(cmin, ee.c - ee.f));
				if (f > 0) {
					ee.f += f;
					e[i ^ 1].f -= f;
					return f;
				}
			}
		}
		return 0;
	}

	void dinic() {
		d.resize(N);
		pt.resize(N);
		int mf = 0;
		for (A = inf; A; A >>= 1) {
			while (bfs()) {
				fill_n(pt.begin(), N, 0);
				while (dfs(S, inf));
			}
		}
	}

	void addEdge(int u, int v, int c) {
		static int i = 0;
		e.pb({ v, c, 0 });
		e.pb({ u, 0, 0 });
		g[u].pb(i);
		g[v].pb(i ^ 1);
		i += 2;
	}

	void zhfs(int v, vector<bool>& was) {
		was[v] = true;
		for (int i : g[v]) {
			edge& ee = e[i];
			if (ee.c - ee.f > 0 && !was[ee.to]) {
				zhfs(ee.to, was);
			}
		}
	}
};

vi g1[100000];
vector<pii> e;
bool ban[100000];
int w[100000];

void dfs(int v) {
	ban[v] = true;
	for (int to : g1[v]) if(!ban[to]) dfs(to);
}

vector<pii> pl[100];
vi pm[100];

int32_t main() {
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	//ifstream cin("in.txt");
	cin >> n >> m;
	for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) if(i != j) d[i][j] = inf;
	for (int i = 0; i < m; i++) {
		int u, v; cin >> u >> v; --u; --v; d[u][v] = d[v][u] = 1;
	}
	for (int k = 0; k < n; k++) for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
	cin >> s >> b >> k;
	for (int i = 0; i < s; i++) cin >> ss[i].x >> ss[i].a >> ss[i].f >> ss[i].p, --ss[i].x;
	for (int i = 0; i < b; i++) cin >> bb[i].x >> bb[i].d >> bb[i].g, --bb[i].x, pl[bb[i].x].pb({ bb[i].d, bb[i].g });
	for (int i = 0; i < n; i++) {
		if (pl[i].empty()) continue;
		sort(all(pl[i]));
		pm[i].resize(sz(pl[i]));
		pm[i][0] = pl[i][0].second;
		for (int j = 1; j < sz(pm[i]); j++) {
			pm[i][j] = max(pm[i][j - 1], pl[i][j].second);
		}
	}
	vi broken;
	maxflow grape;
	grape.N = s + 2;
	grape.S = grape.N - 2;
	grape.T = grape.N - 1;
	grape.g.resize(grape.N);
	vi ord(s); iota(all(ord), 0);
	sort(all(ord), [](int i, int j) { return ss[i].a < ss[j].a; });
	vi pt(n, -1);
	for (int i : ord) {
		int hi = -1;
		//for (int p = 0; p < n; p++) if (ss[i].f >= d[ss[i].x][p]) for (pii bas : pl[p]) if (ss[i].a >= bas.first) hi = max(hi, bas.second);
		// me for (int p = 0; p < n; p++) if (ss[i].f >= d[ss[i].x][p]) for (int t = 0; t < sz(pl[p]) && ss[i].a >= pl[p][t].first; t++) hi = max(hi, pm[p][t]);
 		//for (int j = 0; j < b; j++) if (ss[i].a >= bb[j].d && ss[i].f >= d[ss[i].x][bb[j].x]) hi = max(hi, bb[j].g);
		for (int p = 0; p < n; p++) {
			while (pt[p] + 1 < sz(pl[p]) && ss[i].a >= pl[p][pt[p] + 1].first) pt[p]++;
			if (pt[p] != -1) hi = max(hi, pm[p][pt[p]]);
		}
		if (hi == -1) broken.pb(i);
		else {
			hi -= ss[i].p;
			if (hi < 0) grape.addEdge(i, grape.T, -hi);
			else if (hi > 0) grape.addEdge(grape.S, i, hi);
			w[i] = hi;
		}
	}
	for (int i = 0; i < k; i++) {
		int u, v; cin >> u >> v; --u; --v;
		g1[v].pb(u); e.pb({ u, v });
	}
	for (int u : broken) if (!ban[u]) dfs(u);
	for (pii r : e) {
		int u = r.first, v = r.second;
		if (!ban[u] && !ban[v]) grape.addEdge(u, v, inf);
	}
	grape.dinic();
	vector<bool> was(grape.N, false);
	grape.zhfs(grape.S, was);
	ll ans = 0;
	for (int u = 0; u < s; u++) {
		if (was[u]) {
			ans += w[u];
		}
	}
	cout << ans;
}

#include <bits/stdc++.h>
#define rep(i,n) for(ll i=1;i<=n;i++)
#define fs first
#define sc second
#define MAXN 200005
#define LIMIT 1500
#define LOGN 18
#define ll long long
#define pb push_back
#define ld long double
#define eps 1e-6
#define endl '\n'
#define lc 2*pos
#define rc 2*pos+1
#define mod 1000000007
using namespace std;
set<ll>adj[160005],inv[160005];
ll dist[105][105],mxG[105];
ll n,m,s,b;
struct space{
    ll x,a,f,p,gold,idx;
}sp[100005];
struct bse{
    ll x,d,g;
}bs[100005];
vector<ll> order;
queue<ll>node;
bool visit[160005];
ll memo[160005];
void dfs(ll x){
	//cout<<x<<endl;
    visit[x]=1;
    for(auto it:adj[x]){
        if(visit[it])continue;
        dfs(it);
    }
    order.push_back(x);
    return;
}
void scc(ll x){
    visit[x]=1;
    //cout<<x<<endl;
    for(auto it:inv[x]){
        if(visit[it])continue;
        scc(it);
    }
    node.push(x);
    return;
}
ll dp(int pos){
    if(memo[pos]!=-1)return memo[pos];
    ll sum=sp[pos].gold;
    for(auto it:adj[pos]){
        sum+=dp(it);
    }

    return memo[pos]=max(sum, 0ll);
}
bool cmps(space a, space b){
    return a.a<b.a;
}
bool cmpb(bse a, bse b){
    return a.d<b.d;
}
int main () {

    //freopen("input.txt","r",stdin);
    ll k;
    scanf("%lld%lld", &n, &m);
    memset(dist,-1,sizeof(dist));
    rep(i,m){
        int u,v;
        cin>>u>>v;
        dist[u][v]=1;
        dist[v][u]=1;
    }
    rep(i,n)dist[i][i]=0;
    rep(k,n){
        rep(i,n){
            rep(j,n){
                if(dist[i][k]==-1||dist[k][j]==-1)continue;
                if(dist[i][j]==-1)dist[i][j]=dist[i][k]+dist[k][j];
                else dist[i][j]=min(dist[i][j],dist[i][k]+dist[k][j]);
                //cout<<i<<' '<<j<<' '<<dist[i][j]<<endl;
            }
        }
    }
    cin>>s>>b>>k;
    rep(i,s){
        int x,a,f,p;
        cin>>x>>a>>f>>p;
        sp[i]={x,a,f,-p,-p,i};
    }
    rep(i,b){
        int x,d,g;
        cin>>x>>d>>g;
        bs[i]={x,d,g};
    }
    sort(sp+1,sp+1+s,cmps);
    sort(bs+1,bs+1+b,cmpb);
    int tmp=1;
    rep(i,s){
        while(tmp<=b&&bs[tmp].d<=sp[i].a){
            mxG[bs[tmp].x]=max(mxG[bs[tmp].x],bs[tmp].g);
            //cout<<bs[tmp].g<<endl;
            tmp++;
        }
        rep(j,n){
            if(dist[sp[i].x][j]==-1||dist[sp[i].x][j]>sp[i].f)continue;
            sp[i].gold=max(sp[i].gold,mxG[j]+sp[i].p);
        }
        //cout<<sp[i].gold<<endl;
    }
    int posi[100005];
    rep(i,s)posi[sp[i].idx]=i;
    rep(i,k){
        int s1,s2;
        cin>>s1>>s2;
        s1=posi[s1],s2=posi[s2];
        //cout<<s1<<s2<<endl;
        adj[s2].insert(s1);
        inv[s1].insert(s2);
    }
    rep(i,s)if(inv[i].size()==0)adj[0].insert(i);
    dfs(0);
    rep(i,s){
        if(visit[i])continue;
        dfs(i);
    }
    reverse(order.begin(),order.end());
    memset(visit,0,sizeof(visit));
    for(auto it:order){
        if(visit[it])continue;
        //cout<<"first"<<it<<endl;
        scc(it);
        //cout<<it<<' '<<node.size()<<endl;
        ll cur=node.front();
        node.pop();
        while(!node.empty()){
            ll now=node.front();
            node.pop();
            sp[cur].gold+=sp[now].gold;
            for(auto it:inv[now]){
            	//cout<<cur<<' '<<now<<' '<<it<<endl;
                adj[it].erase(now);
                if(it!=cur)
                adj[it].insert(cur);
            }
            for(auto it:adj[now]){
            	if(it!=cur)
                adj[cur].insert(it);
            }
            adj[cur].erase(now);
        }
    }
    // for(int i=0;i<=s;i++){
    //     cout<<"node "<<i<<' '<<sp[i].gold<<endl;
    //     for(auto it:adj[i])cout<<it<<endl;
    // }
    memset(memo,-1,sizeof(memo));
    cout<<dp(0)<<endl;
    //cout<<"test\n";
}

#include <bits/stdc++.h>

#define fast_cin() ios_base::sync_with_stdio(false); cin.tie(0);
#define pb push_back

using namespace std;

typedef long double ld;
typedef long long ll;
typedef long long LL;
typedef pair <int, int> pii;
typedef pair <ll, ll> pll;

struct Edge {
  int u, v;
  LL cap, flow;
  Edge() {}
  Edge(int u, int v, LL cap): u(u), v(v), cap(cap), flow(0) {}
};

struct Dinic {
  int N;
  vector<Edge> E;
  vector<vector<int>> g;
  vector<int> d, pt;

  Dinic(int N): N(N), E(0), g(N), d(N), pt(N) {}

  void AddEdge(int u, int v, LL cap) {
    if (u != v) {
      E.emplace_back(Edge(u, v, cap));
      g[u].emplace_back(E.size() - 1);
      E.emplace_back(Edge(v, u, 0));
      g[v].emplace_back(E.size() - 1);
    }
  }

  bool BFS(int S, int T) {
    queue<int> q({S});
    fill(d.begin(), d.end(), N + 1);
    d[S] = 0;
    while(!q.empty()) {
      int u = q.front(); q.pop();
      if (u == T) break;
      for (int k: g[u]) {
        Edge &e = E[k];
        if (e.flow < e.cap && d[e.v] > d[e.u] + 1) {
          d[e.v] = d[e.u] + 1;
          q.emplace(e.v);
        }
      }
    }
    return d[T] != N + 1;
  }

  LL DFS(int u, int T, LL flow = -1) {
    if (u == T || flow == 0) return flow;
    for (int &i = pt[u]; i < g[u].size(); ++i) {
      Edge &e = E[g[u][i]];
      Edge &oe = E[g[u][i]^1];
      if (d[e.v] == d[e.u] + 1) {
        LL amt = e.cap - e.flow;
        if (flow != -1 && amt > flow) amt = flow;
        if (LL pushed = DFS(e.v, T, amt)) {
          e.flow += pushed;
          oe.flow -= pushed;
          return pushed;
        }
      }
    }
    return 0;
  }

  LL MaxFlow(int S, int T) {
    LL total = 0;
    while (BFS(S, T)) {
      fill(pt.begin(), pt.end(), 0);
      while (LL flow = DFS(S, T))
        total += flow;
    }
    return total;
  }
};

struct ship_t {
	int x, a, f, p;
};

struct base_t {
	int x, d, g;
	bool operator<(const base_t &o) const {
		return d < o.d;
	}
};

const int N = 1e2 + 10, S = 1e5 + 10;
const ll inf = 1e12 + 42;

ship_t ship[S];
base_t base[S];
ll g[N][N];
vector<int> dep[S];
vector<pll> bases_at[N];
bool seen[S];
ll val[S];

int main()
{
	fast_cin();
	int n, m;
	cin >> n >> m;
	for (int i = 1; i <= n; ++i) {
		for (int j = i + 1; j <= n; ++j) {
			g[i][j] = g[j][i] = inf;
		}
	}
	for (int i = 0; i < m; ++i) {
		int u, v;
		cin >> u >> v;
		g[u][v] = g[v][u] = min(g[u][v], 1ll);
	}
	for (int k = 1; k <= n; ++k) {
		for (int i = 1; i <= n; ++i) {
			for (int j = 1; j <= n; ++j) {
				g[i][j] = min(g[i][j], g[i][k] + g[k][j]);
			}
		}
	}
	int s, b, k;
	cin >> s >> b >> k;
	for (int i = 1; i <= s; ++i) {
		cin >> ship[i].x >> ship[i].a >> ship[i].f >> ship[i].p;
	}
	for (int i = 1; i <= b; ++i) {
		cin >> base[i].x >> base[i].d >> base[i].g;
	}
	sort(base + 1, base + 1 + b);
	for (int i = 1; i <= b; ++i) {
		int p = base[i].x;
		if (bases_at[p].empty() or bases_at[p].back().second < base[i].g) {
			bases_at[p].pb({base[i].d, base[i].g});
		}
	}
	Dinic dinic(s + 2);
	int source = 0, sink = s + 1;
	ll ans = 0;
	for (int i = 1; i <= s; ++i) {
		for (int p = 1; p <= n; ++p) {
			if (g[ship[i].x][p] > ship[i].f) {
				continue;
			}
			auto it = upper_bound(bases_at[p].begin(), bases_at[p].end(), make_pair(ll(ship[i].a), inf));
			if (it != bases_at[p].begin()) {
				--it;
				val[i] = max(val[i], it->second);
			}
		}
		val[i] -= ship[i].p;
		if (val[i] >= 0) {
			ans += val[i];
			dinic.AddEdge(source, i, val[i]);
		} else {
			dinic.AddEdge(i, sink, -val[i]);
		}
	}
	for (int i = 1; i <= k; ++i) {
		int u, v;
		cin >> u >> v;
		dep[u].pb(v);
	}
	for (int i = 1; i <= s; ++i) {
		if (val[i] < 0) {
			continue;
		}
		vector<int> vis = {i};
		queue<int> q;
		q.push(i);
		seen[i] = true;
		while (!q.empty()) {
			int u = q.front();
			q.pop();
			if (val[u] < 0) {
				dinic.AddEdge(i, u, inf);
			}
			for (auto &v : dep[u]) {
				if (!seen[v]) {
					seen[v] = true;
					vis.pb(v);
					q.push(v);
				}
			}
		}
		for (auto &u : vis) {
			seen[u] = false;
		}
	}
	cout << ans - dinic.MaxFlow(source, sink);
}

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int mod=1e9+7;
const int maxm=100+10;
const int maxn=3e5+10;
const int N=1e5+10;
const int inf=0x3f3f3f3f;
namespace io {
    const int SIZE = (1 << 21) + 1;
    char ibuf[SIZE], *iS, *iT, obuf[SIZE], *oS = obuf, *oT = oS + SIZE - 1, c, qu[55]; int f, qr;
    // getchar
    #define gc() (iS == iT ? (iT = (iS = ibuf) + fread (ibuf, 1, SIZE, stdin), (iS == iT ? EOF : *iS ++)) : *iS ++)
    // print the remaining part
    inline void flush () {
        fwrite (obuf, 1, oS - obuf, stdout);
        oS = obuf;
    }
    // putchar
    inline void putc (char x) {
        *oS ++ = x;
        if (oS == oT) flush ();
    }
    template<typename A>
    inline bool read (A &x) {
        for (f = 1, c = gc(); c < '0' || c > '9'; c = gc()) if (c == '-') f = -1;else if(c==EOF)return 0;
        for (x = 0; c <= '9' && c >= '0'; c = gc()) x = x * 10 + (c & 15); x *= f;
        return 1;
    }
    inline bool read (char &x) {
        while((x=gc())==' '||x=='\n' || x=='\r');
        return x!=EOF;
    }
    inline bool read(char *x){
        while((*x=gc())=='\n' || *x==' '||*x=='\r');
        if(*x==EOF)return 0;
        while(!(*x=='\n'||*x==' '||*x=='\r'||*x==EOF))*(++x)=gc();
        *x=0;
        return 1;
    }
    template<typename A,typename ...B>
    inline bool read(A &x,B &...y){
        return read(x)&&read(y...);
    }
    template<typename A>
    inline bool write (A x) {
        if (!x) putc ('0'); if (x < 0) putc ('-'), x = -x;
        while (x) qu[++ qr] = x % 10 + '0',  x /= 10;
        while (qr) putc (qu[qr --]);
        return 0;
    }
    inline bool write (char x) {
        putc(x);
        return 0;
    }
    inline bool write(const char *x){
        while(*x){putc(*x);++x;}
        return 0;
    }
    inline bool write(char *x){
        while(*x){putc(*x);++x;}
        return 0;
    }
    template<typename A,typename ...B>
    inline bool write(A x,B ...y){
        return write(x)||write(y...);
    }
    //no need to call flush at the end manually!
    struct Flusher_ {~Flusher_(){flush();}}io_flusher_;
}
using io :: read;
using io :: putc;
using io :: write;
int dis[maxm][maxm];
map<int,int> mp;
struct base{
	int def,gold,mmax;
	friend bool operator<(base a,base b)
	{
		return a.def<b.def;
	}
};
struct ship{
	int x,att,fuel,pri;
}a[N];
vector<base> v[maxm];
int val[N];
int s,t;
int now[N],dep[N],head[N];
struct edge{
	int v,w,nxt;
}e[maxn];
int ecnt;
void addedge(int u,int v,int w)
{
	e[ecnt]={v,w,head[u]};
	head[u]=ecnt++;
	e[ecnt]={u,0,head[v]};
	head[v]=ecnt++;
}
int bfs()//重新建图，按层次建图
{
    queue<int> q;
    while(!q.empty())
        q.pop();
    for(int i=s;i<=t;i++)
    {
    	dep[i]=-1;
    	now[i]=-1; //now[i]表示i的当前弧
    }
    dep[s] = 0; //dep为层次
    q.push(s);
    now[s]=head[s];
    while(!q.empty()){
        int u = q.front();
        q.pop();
        for(int i=head[u]; i!=-1; i=e[i].nxt){
        	int v=e[i].v;
            if(e[i].w > 0 && dep[v] == -1){//如果可以到达且还没有访问，可以到达的条件是剩余容量大于0，没有访问的条件是当前层数还未知
                dep[v] = dep[u] + 1;
                now[v]=head[v];
                q.push(v);
            }
        }
    }
    return dep[t] != -1;
}
int dfs(int u, int mi)//查找路径上的最小流量
{
    if(mi==0||u == t)
        return mi;
    int tmp,sum=0;
    for(int i=now[u]; i!=-1&&mi; i=e[i].nxt){
    	now[u]=i; //当前弧优化
    	int v=e[i].v;
        if(e[i].w > 0 && dep[v] == dep[u] + 1){
			tmp = dfs(v, min(mi, e[i].w));
            e[i].w -= tmp;
            e[i^1].w += tmp;
            sum+=tmp; //一次增广跑多条路，sum为流量总和
            mi-=tmp; //用掉了tmp
            if(!mi) break;
        }
    }
    return sum;
}
ll dinic()
{
    ll ans = 0;
    while(bfs()){
        ans+=dfs(s,inf);
    }
    return ans;
}
int main()
{
	memset(head,-1,sizeof(head));
	memset(dis,0x3f,sizeof(dis));
	int n,m;
	read(n,m);
	for(int i=1;i<=n;i++) dis[i][i]=0;
	for(int i=1;i<=m;i++)
	{
		int u,v;
		read(u,v);
		dis[u][v]=dis[v][u]=1;
	}
	for(int k=1;k<=n;k++)
		for(int i=1;i<=n;i++)
			for(int j=1;j<=n;j++)
				dis[i][j]=min(dis[i][k]+dis[k][j],dis[i][j]);
	int snum,bnum,k;
	read(snum,bnum,k);
	//assert(bnum<=n);
	for(int i=1;i<=snum;i++)
	{
		int x,att,fu,pri;
		read(x,att,fu,pri);
		a[i]={x,att,fu,pri};
	}
	for(int i=1;i<=bnum;i++)
	{
		int x,def,gol;
		read(x,def,gol);
		//assert((!mp[x])||mp[x]==def);
		//b[x]={def,gol};
		//mp[x]=def;
		v[x].push_back({def,gol,gol});
	}
	for(int i=1;i<=n;i++)
	{
		sort(v[i].begin(),v[i].end());
		for(int j=1;j<v[i].size();j++) v[i][j].mmax=max(v[i][j].gold,v[i][j-1].mmax);
	}
	for(int i=1;i<=snum;i++) val[i]=-inf;
	for(int i=1;i<=snum;i++)
	{
		for(int j=1;j<=n;j++)
		{
			if(a[i].fuel>=dis[a[i].x][j])
			{
				//val[i]=max(val[i],b[j].gold-a[i].pri);
				//int pos=v[a[i].x].lower_bound({a[i].att,inf,0})-v[a[i].x].begin();
				int l=0,r=v[j].size()-1,pos=-1;
				while(l<=r)
				{
					int mid=l+r>>1;
					if(v[j][mid].def<=a[i].att)
					{
						l=mid+1,pos=mid;
					}
					else r=mid-1;
				}
				if(pos<0) continue;
				val[i]=max(val[i],v[j][pos].mmax-a[i].pri);
			}
		}
	}
	s=0,t=snum+1;
	for(int i=1;i<=k;i++)
	{
		int u,v;
		read(u,v);
		addedge(v,u,inf);
	}
	ll tot=0;
	for(int i=1;i<=snum;i++)
	{
		//printf("val[%d]=%d\n",i,val[i]);
		//if(val[i]<=-inf) continue;
		if(val[i]>=0)
		{
			tot+=val[i];
			addedge(i,t,val[i]);
		}
		if(val[i]<0) addedge(s,i,-val[i]);
	}
	tot-=dinic();
	printf("%lld\n",tot);
	return 0;
}

#include<bits/stdc++.h>
using namespace std;

#define ll long long
#define all(aaa) aaa.begin(), aaa.end()

struct E {
    int to, i;
};

const ll INF = 1e18;
const int N = 105, M = 1e5 + 5, V = 2005, Z = 3e6, S = V - 2, T = V - 1;
int cost[M], best[M], pos[M], atk[M], fuel[M], dt[V], p[V];
ll cp[Z], fl[Z], d[N][N];
int ce = 0;
vector<E> g[V];
vector<pair<int, int>> lt[N];
bool notFree[M];

void addEdge(int a, int b, ll c) {
    cp[ce] = c;
    g[a].push_back({b, ce++});
    cp[ce] = 0;
    g[b].push_back({a, ce++});
}

bool bfs() {
    queue<int> q;
    fill(dt, dt + V, -1);
    dt[S] = 0;
    q.push(S);

    while (!q.empty()) {
        int node = q.front();
        q.pop();
        for (E e : g[node]) {
            if (cp[e.i] > fl[e.i] && dt[e.to] == -1) {
                dt[e.to] = dt[node] + 1;
                q.push(e.to);
            }
        }
    }

    return dt[T] != -1;
}

ll dfs(int node, ll flow) {
    if (node == T)
        return flow;
    for (int &i = p[node]; i < g[node].size(); i++) {
        E e = g[node][i];
        if (cp[e.i] > fl[e.i] && dt[e.to] == dt[node] + 1)  {
            ll ret = dfs(e.to, min(flow, cp[e.i] - fl[e.i]));
            if (ret) {
                fl[e.i] += ret;
                fl[e.i ^ 1] -= ret;
                return ret;
            }
        }
    }
    return 0;
}

ll maxFlow() {
    ll flow = 0;
    while (bfs()) {
        memset(p, 0, sizeof(p));
        ll ret = 0;
        while (ret = dfs(S, INF)) {
            flow += ret;
        }
    }
    return flow;
}

signed main() {
#ifdef HOME
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#endif
    ios_base::sync_with_stdio(0);
    cin.tie(0);

    int n, m;
    cin >> n >> m;

    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            d[i][j] = INF;
        }
        d[i][i] = 0;
    }

    for (int i = 0; i < m; i++) {
        int a, b;
        cin >> a >> b;
        a--, b--;
        d[b][a] = d[a][b] = 1;
    }

    for (int i = 0; i < n; i++)  {
        for (int j = 0; j < n; j++) {
            for (int k = 0; k < n; k++) {
                d[j][k] = min(d[j][i] + d[i][k], d[j][k]);
            }
        }
    }

    int s, b, k;
    cin >> s >> b >> k;

    for (int i = 0; i < s; i++) {
        cin >> pos[i] >> atk[i] >> fuel[i] >> cost[i];
        pos[i]--;
    }

    for (int i = 0; i < b; i++) {
        int pl, def, gold;
        cin >> pl >> def >> gold;
        pl--;
        lt[pl].push_back({def, gold});
    }

    for (int i = 0; i < n; i++) {
        lt[i].push_back({0, 0});
        sort(all(lt[i]));
        for (int j = 1; j < lt[i].size(); j++) {
            lt[i][j].second = max(lt[i][j].second, lt[i][j - 1].second);
        }
    }

    for (int i = 0; i < s; i++) {
        for (int j = 0; j < n; j++) {
            if (d[pos[i]][j] <= fuel[i]) {
                int q = upper_bound(lt[j].begin(), lt[j].end(), make_pair(atk[i] + 1, -1)) - lt[j].begin();
                best[i] = max(best[i], lt[j][q - 1].second);
            }
        }
    }

    vector<int> vip;
    vector<pair<int, int>> dep;

    for (int i = 0; i < k; i++) {
        int a, b;
        cin >> a >> b;
        a--, b--;
        vip.push_back(a);
        vip.push_back(b);

        notFree[a] = notFree[b] = 1;

        dep.push_back({a, b});
    }

    sort(all(vip));
    vip.erase(unique(all(vip)), vip.end());

    ll ans = 0;

    for (int i = 0; i < s; i++) {
        if (!notFree[i] && best[i] > cost[i]) {
            ans += best[i] - cost[i];
        }
    }

    for (int i = 0; i < vip.size(); i++) {
        int j = vip[i];
        if (cost[j] > best[j]) {
            addEdge(i, T, cost[j] - best[j]);
        }
        else {
            addEdge(S, i, best[j] - cost[j]);
            ans += best[j] - cost[j];
        }
    }

    for (auto e : dep) {
        e.first = lower_bound(all(vip), e.first) - vip.begin();
        e.second = lower_bound(all(vip), e.second) - vip.begin();
        addEdge(e.first, e.second, INF);
    }

    ans -= maxFlow();

    cout << ans;

    return 0;
}

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    ll n, m;
    cin >> n >> m;
    vector<vector<ll>> dist((size_t) n, vector<ll>((size_t) n, (ll) 1e16));
    for (ll i = 0; i < n; i++) {
        dist[i][i] = (ll) 0;
    }
    for (ll i = 0; i < m; i++) {
        ll u, v;
        cin >> u >> v;
        u--, v--;
        dist[u][v] = dist[v][u] = 0;
    }
    for (ll k = 0; k < n; k++) {
        for (ll i = 0; i < n; i++) {
            for (ll j = 0; j < n; j++) {
                dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
            }
        }
    }
    ll s, b, k;
    cin >> s >> b >> k;
    vector<tuple<ll, ll, ll, ll>> x((size_t) s);
    for (ll i = 0; i < s; i++) {
        cin >> get<0>(x[i]) >> get<1>(x[i]) >> get<2>(x[i]) >> get<3>(x[i]);
        get<0>(x[i])--;
    }
    vector<tuple<ll, ll, ll>> y((size_t) b);
    for (ll i = 0; i < b; i++) {
        cin >> get<0>(y[i]) >> get<1>(y[i]) >> get<2>(y[i]);
        get<0>(y[i])--;
    }
    vector<map<ll, ll>> bases((size_t) n);
    for (ll i = 0; i < b; i++) {
        bases[get<0>(y[i])][get<1>(y[i])] = get<2>(y[i]);
    }
    for (ll i = 0; i < n; i++) {
        for (auto j = bases[i].begin(); j != bases[i].end();) {
            if (j == bases[i].begin() || j->second > prev(j)->second) {
                j++;
            } else {
                j = bases[i].erase(j);
            }
        }
    }
    vector<ll> damages((size_t) s, (ll) -1e16);
    for (ll i = 0; i < s; i++) {
        for (ll j = 0; j < n; j++) {
            if (get<2>(x[i]) >= dist[get<0>(x[i])][j]) {
                auto it = bases[j].upper_bound(get<1>(x[i]));
                if (it != bases[j].begin()) {
                    damages[i] = max(damages[i], prev(it)->second - get<3>(x[i]));
                }
            }
        }
    }
    vector<vector<ll>> init_adj((size_t) s), init_adj_rev((size_t) s);
    vector<vector<pair<ll, ll>>> adj((size_t) s + 2);
    vector<map<ll, ll>> flows((size_t) s + 2);
    auto add_edge = [&](ll u, ll v, ll w) {
        adj[u].emplace_back(v, w);
        adj[v].emplace_back(u, 0);
        flows[u][v] = 0;
        flows[v][u] = 0;
    };
    for (ll i = 0; i < k; i++) {
        ll u, v;
        cin >> u >> v;
        u--, v--;
        if (u != v) {
            init_adj[u].push_back(v);
            init_adj_rev[v].push_back(u);
            add_edge(u, v, (ll) 1e16);
        }
    }
    ll o = 0;
    for (ll u = 0; u < s; u++) {
        if (damages[u] > 0) {
            if (!init_adj[u].empty()) {
                add_edge(s, u, damages[u]);
            } else {
                o += damages[u];
            }
        } else {
            if (!init_adj_rev[u].empty()) {
                add_edge(u, s + 1, -damages[u]);
            }
        }
    }
    vector<bool> visited;
    vector<ll> path;
    function<ll(ll)> visit = [&](ll u) {
        if (!visited[u]) {
            visited[u] = true;
            path.push_back(u);
            if (u == s + 1) {
                return (ll) 1e16;
            } else {
                for (auto[v, w] : adj[u]) {
                    if (w - flows[u][v] > 0) {
                        ll a = visit(v);
                        if (a > 0) {
                            return min(w - flows[u][v], a);
                        }
                    }
                }
            }
            path.pop_back();
        }
        return (ll) 0;
    };
    while (true) {
        visited.assign((ll) s + 2, false);
        path.clear();
        ll a = visit(s);
        if (a > 0) {
            for (ll i = 1; i < (ll) path.size(); i++) {
                flows[path[i - 1]][path[i]] += a;
                flows[path[i]][path[i - 1]] -= a;
            }
            o += a;
        } else {
            break;
        }
    }
    cout << o << endl;
    return 0;
}

#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <utility>
#include <limits>

struct base_t {
    int position, defense, gold;
    friend std::istream& operator >> (std::istream& flux, base_t& b) {
        flux >> b.position >> b.defense >> b.gold;
        return flux;
    }
    bool operator < (const base_t& b) const {
        if (this->defense != b.defense)
            return this->defense < b.defense;
        return this->gold < b.gold;
    }
};

struct ship_t {
    int position, strength, fuel, price;
    friend std::istream& operator >> (std::istream& flux, ship_t& s) {
        flux >> s.position >> s.strength >> s.fuel >> s.price;
        return flux;
    }
};

struct Flow_Edge {
    int from, to;
    int64_t capacity, flow = 0LL;
    Flow_Edge (const int& from, const int& to, const int64_t& capacity): from (from), to (to), capacity (capacity) {
    }
};

constexpr auto Inf = std::numeric_limits <int64_t>::max ();
constexpr auto OO = std::numeric_limits <int>::max ();
constexpr auto inf = std::numeric_limits <int64_t>::min ();
using Ip = std::pair <int, int>;
using Vi = std::vector <int>;
using VVi = std::vector <Vi>;
using Vi64 = std::vector <int64_t>;
using VVi64 = std::vector <Vi64>;
using VIp = std::vector <Ip>;
using VVIp = std::vector <VIp>;
using Vf = std::vector <Flow_Edge>;
using Vs = std::vector <ship_t>;
using Vb = std::vector <base_t>;
using Qi = std::queue <int>;

struct Dinic {
    Vf Edges;
    VVi Adj;
    int n, s, t;
    Vi Level, Ptr;
    Qi Q;
    Dinic (const int& n, const int& s, const int& t): n (n), s (s), t (t) {
        Adj.resize (n), Level.resize (n), Ptr.resize (n);
    }
    void add_edge (const int& u, const int& v, const int64_t& cap) {
        Edges.emplace_back (Flow_Edge (u, v, cap));
        Adj[u].emplace_back (Edges.size () - 1);
        Edges.emplace_back (Flow_Edge (v, u, 0));
        Adj[v].emplace_back (Edges.size () - 1);
    }
    bool bfs () {
        while (!Q.empty ()) {
            int v = Q.front (); Q.pop ();
            for (const auto& id: Adj[v]) {
                if (Edges[id].capacity - Edges[id].flow < 1)
                    continue;
                if (Level[Edges[id].to] != -1)
                    continue;
                Level[Edges[id].to] = Level[v] + 1;
                Q.push (Edges[id].to);
            }
        }
        return Level[t] != -1;
    }
    int64_t dfs (const int& v, const int64_t& pushed) {
        if (!pushed)
            return 0LL;
        if (v == t)
            return pushed;
        for (int& cid = Ptr[v]; cid < (int)Adj[v].size (); ++ cid) {
            int id = Adj[v][cid], u = Edges[id].to;
            if (Level[v] + 1 != Level[u] || Edges[id].capacity - Edges[id].flow < 1)
                continue;
            int64_t transport = dfs (u, Edges[id].capacity - Edges[id].flow);
            if (!transport)
                continue;
            Edges[id].flow += transport;
            Edges[id ^ 1].flow -= transport;
            return transport;
        }
        return 0LL;
    }
    int64_t max_flow () {
        int64_t f = 0LL;
        while (true) {
            std::fill (Level.begin (), Level.end (), -1);
            Level[s] = 0;
            Q.push (s);
            if (!bfs ())
                break;
            std::fill (Ptr.begin (), Ptr.end (), 0);
            while (int64_t pushed = dfs (s, Inf))
                f += pushed;
        }
        return f;
    }
};

int n, m, u, v, s, b, k;
Vi64 Value;
VVi64 Cost;
Vs Ships;
Vb Bases;
VVIp Bases_at;

int main () {
    std::cin >> n >> m;
    Cost.assign (n + 1, Vi64 (n + 1, Inf));
    for (int i = 1; i <= m; ++ i)
        std::cin >> u >> v, Cost[u][v] = Cost[v][u] = std::min (Cost[u][v], 1LL);

    for (int k = 1; k <= n; ++ k)
        for (int i = 1; i <= n; ++ i)
            for (int j = 1; j <= n; ++ j)
                Cost[i][j] = std::min (Cost[i][j], Cost[i][k] + Cost[k][j]);

    std::cin >> s >> b >> k;
    Value.resize (s + 1), Bases_at.resize (n + 1);
    Ships.resize (s + 1), Bases.resize (b + 1);
    for (int i = 1; i <= s; ++ i)
        std::cin >> Ships[i];
    for (int i = 1; i <= b; ++ i)
        std::cin >> Bases[i];

    std::sort (Bases.begin () + 1, Bases.end ());
    for (int i = 1; i <= b; ++ i) {
        int pos = Bases[i].position;
        //if (Bases_at[pos].empty () || Bases_at[pos].back ().second < Bases[i].gold)
        Bases_at[pos].emplace_back (std::make_pair (Bases[i].defense, Bases[i].gold));
    }

    Dinic dinic (s + 2, 0, s + 1);
    int source = 0, sink = s + 1;
    int64_t ans = 0LL;
    for (int i = 1; i <= s; ++ i) {
        bool found = false;
        for (int p = 1; p <= n; ++ p) {
            if (Cost[Ships[i].position][p] > Ships[i].fuel)
                continue;
            auto it = std::upper_bound (Bases_at[p].begin (), Bases_at[p].end (), std::make_pair (Ships[i].strength, OO));
            if (it != Bases_at[p].begin ())
                -- it, found = true, Value[i] = std::max (Value[i], 1LL * it->second);
        }
        Value[i] -= Ships[i].price;
        if (!found)
            Value[i] = inf;
        if (Value[i] >= 0)
            ans += Value[i], dinic.add_edge (source, i, Value[i]);
        else
            dinic.add_edge (i, sink, -Value[i]);
    }

    for (int i = 1; i <= k; ++ i)
        std::cin >> u >> v,
        dinic.add_edge (u, v, Inf);

    std::cout << ans - dinic.max_flow ();

    return 0;
}

#include <iostream>
#include <fstream>
#include <numeric>
#include <iomanip>
#include <cstring>
#include <string>
#include <algorithm>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <deque>

#define int ll
#define sz(a) (int)((a).size())
#define all(a) (a).begin(), (a).end()
#define pb push_back

using namespace std; using ll = long long; using vi = vector<int>; using pii = pair<int, int>; using ld = long double;

const ll inf = (ll)1e18 + 100;

int n, m;
int d[100][100];
int s, b, k;

struct ship {
	int x, a, f, p;
} ss[100000];

struct base {
	int x, d, g;
} bb[100000];

struct maxflow {
	struct edge {
		int to, c, f;
	};

	vector<edge> e;
	vector<vi> g;
	int N, S, T;
	vi pt, d;
	int A;

	bool bfs() {
		fill_n(d.begin(), N, inf);
		d[S] = 0;
		queue<int> q;
		q.push(S);
		while (!q.empty()) {
			int v = q.front();
			q.pop();
			for (int i : g[v]) {
				edge& ee = e[i];
				if (ee.c - ee.f >= A && d[ee.to] == inf) {
					d[ee.to] = d[v] + 1;
					q.push(ee.to);
				}
			}

		}
		return (d[T] != inf);
	}

	int dfs(int v, int cmin) {
		if (v == T) {
			return cmin;
		}
		for (; pt[v] < sz(g[v]); pt[v]++) {
			int i = g[v][pt[v]];
			edge& ee = e[i];
			if (ee.c - ee.f >= A && d[ee.to] == d[v] + 1) {
				int f = dfs(ee.to, min(cmin, ee.c - ee.f));
				if (f > 0) {
					ee.f += f;
					e[i ^ 1].f -= f;
					return f;
				}
			}
		}
		return 0;
	}

	void dinic() {
		d.resize(N);
		pt.resize(N);
		int mf = 0;
		for (A = inf; A; A >>= 1) {
			while (bfs()) {
				fill_n(pt.begin(), N, 0);
				while (dfs(S, inf));
			}
		}
	}

	void addEdge(int u, int v, int c) {
		static int i = 0;
		e.pb({ v, c, 0 });
		e.pb({ u, 0, 0 });
		g[u].pb(i);
		g[v].pb(i ^ 1);
		i += 2;
		//cout << u << ' ' << v << endl;
	}

	void zhfs(int v, vector<bool>& was) {
		was[v] = true;
		for (int i : g[v]) {
			edge& ee = e[i];
			if (ee.c - ee.f > 0 && !was[ee.to]) {
				zhfs(ee.to, was);
			}
		}
	}
};

vi g1[100000];
vector<pii> e;
bool ban[100000];
int w[100000];

void dfs(int v) {
	ban[v] = true;
	for (int to : g1[v]) if(!ban[to]) dfs(to);
}

vector<pii> pl[100];
vi pm[100];

int32_t main() {
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	ifstream cin("in.txt");
	cin >> n >> m;
	for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) if(i != j) d[i][j] = inf;
	for (int i = 0; i < m; i++) {
		int u, v; cin >> u >> v; --u; --v; d[u][v] = d[v][u] = 1;
	}
	for (int k = 0; k < n; k++) for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
	cin >> s >> b >> k;
	for (int i = 0; i < s; i++) cin >> ss[i].x >> ss[i].a >> ss[i].f >> ss[i].p, --ss[i].x;
	for (int i = 0; i < b; i++) cin >> bb[i].x >> bb[i].d >> bb[i].g, --bb[i].x, pl[bb[i].x].pb({ bb[i].d, bb[i].g });
	for (int i = 0; i < n; i++) {
		if (pl[i].empty()) continue;
		sort(all(pl[i]));
		pm[i].resize(sz(pl[i]));
		pm[i][0] = pl[i][0].second;
		for (int j = 1; j < sz(pm[i]); j++) {
			pm[i][j] = max(pm[i][j - 1], pl[i][j].second);
		}
	}
	vi broken;
	maxflow grape;
	grape.N = s + 2;
	grape.S = grape.N - 2;
	grape.T = grape.N - 1;
	grape.g.resize(grape.N);
	vi ord(s); iota(all(ord), 0);
	sort(all(ord), [](int i, int j) { return ss[i].a < ss[j].a; });
	vi pt(n, -1);
	for (int i : ord) {
		int hi = -1;
		//for (int p = 0; p < n; p++) if (ss[i].f >= d[ss[i].x][p]) for (pii bas : pl[p]) if (ss[i].a >= bas.first) hi = max(hi, bas.second);
		// me for (int p = 0; p < n; p++) if (ss[i].f >= d[ss[i].x][p]) for (int t = 0; t < sz(pl[p]) && ss[i].a >= pl[p][t].first; t++) hi = max(hi, pm[p][t]);
 		//for (int j = 0; j < b; j++) if (ss[i].a >= bb[j].d && ss[i].f >= d[ss[i].x][bb[j].x]) hi = max(hi, bb[j].g);
		for (int p = 0; p < n; p++) if(ss[i].f >= d[ss[i].x][p]) {
			while (pt[p] + 1 < sz(pl[p]) && ss[i].a >= pl[p][pt[p] + 1].first) pt[p]++;
			if (pt[p] != -1) hi = max(hi, pm[p][pt[p]]);
		}
		if (hi == -1) broken.pb(i);
		else {
			hi -= ss[i].p;
			w[i] = hi;
			//cout << i << ' ' << w[i] << endl;
		}
	}
	for (int i = 0; i < k; i++) {
		int u, v; cin >> u >> v; --u; --v;
		g1[v].pb(u); e.pb({ u, v });
	}
	for (int u : broken) if (!ban[u]) dfs(u);
	for (int i = 0; i < s; i++) if (!ban[i]) {
		//cout << '!' << i << endl;
		int hi = w[i];
		if (hi < 0) grape.addEdge(i, grape.T, -hi);
		else if (hi > 0) grape.addEdge(grape.S, i, hi);
	}
	for (pii r : e) {
		int u = r.first, v = r.second;
		if (!ban[u] && !ban[v]) grape.addEdge(u, v, inf);
	}
	grape.dinic();
	vector<bool> was(grape.N, false);
	grape.zhfs(grape.S, was);
	ll ans = 0;
	for (int u = 0; u < s; u++) {
		if (was[u]) {
			ans += w[u];
		}
	}
	cout << ans;
}

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int INF = 1e17;
const int maxn = 100015;
const int maxm = 1000005;
int g[105][105];
int num[maxn];
int id[maxn];
int cnt;
void floyed(int n){
    for(int k = 1; k <= n; k++){
        for(int i = 1; i <= n; i++){
            for(int j = 1; j <= n; j++){
                g[i][j] = min(g[i][j], g[i][k]+g[k][j]);
            }
        }
    }
};
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
    while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
struct Edge{
    int to,next,cap,flow;
}edge[maxm];
int tol,head[maxn];
void init()
{
    tol=2;
    memset(head,-1,sizeof(head));
}
void addedge(int u,int v,int w,int rw=0)
{
    edge[tol].to=v;edge[tol].cap=w;edge[tol].flow=0;
    edge[tol].next=head[u];head[u]=tol++;
    edge[tol].to=u;edge[tol].cap=rw;edge[tol].flow=0;
    edge[tol].next=head[v];head[v]=tol++;
}
int Q[maxn];
int dep[maxn],cur[maxn],sta[maxn];
bool bfs(int s,int t,int n)
{
    int front=0,tail=0;
    memset(dep,-1,sizeof(dep[0])*(n+1));
    dep[s]=0;
    Q[tail++]=s;
    while(front<tail){
        int u=Q[front++];
        for(int i=head[u];i!=-1;i=edge[i].next){
            int v=edge[i].to;
            if(edge[i].cap>edge[i].flow&&dep[v]==-1){
                dep[v]=dep[u]+1;
                if(v==t){
                    return true;
                }
                Q[tail++]=v;
            }
        }
    }
    return false;
}
long long dinic(int s,int t,int n)
{
    long long maxflow=0;
    while(bfs(s,t,n)){
        for(int i=0;i<n;i++){
            cur[i]=head[i];
        }
        int u=s,tail=0;
        while(cur[s]!=-1){
            if(u==t){
                int tp=INF;
                for(int i=tail-1;i>=0;i--){
                    tp=min(tp,edge[sta[i]].cap-edge[sta[i]].flow);
                }
                maxflow+=tp;
                for(int i=tail-1;i>=0;i--){
                    edge[sta[i]].flow+=tp;
                    edge[sta[i]^1].flow-=tp;
                    if(edge[sta[i]].cap-edge[sta[i]].flow==0){
                        tail=i;
                    }
                }
                u=edge[sta[tail]^1].to;
            }else if(cur[u]!=-1&&edge[cur[u]].cap>edge[cur[u]].flow&&dep[u]+1==dep[edge[cur[u]].to]){
                sta[tail++]=cur[u];
                u=edge[cur[u]].to;
            }else{
                while(u!=s&&cur[u]==-1){
                    u=edge[sta[--tail]^1].to;
                }
                cur[u]=edge[cur[u]].next;
            }
        }
    }
    return maxflow;
}
//vector<int>fuck[100005];
int fuckacm[100005];
int ps[105];
int in[maxn], out[maxn], shipos[maxn], atk[maxn], f[maxn], p[maxn], baspos[maxn], d[maxn], gold[maxn], val[maxn];
bool svis[maxn];
#define pii pair<int,int>
vector<pii> v1[105];
bool cmp(int x, int y){
    return atk[x] < atk[y];
}
signed main(){
    int n, m, u, v, s, b, k;
    n = read(), m = read();
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n; j++){
            if(i==j) g[i][j] = 0;
            else g[i][j] = g[j][i] = INF;
        }
    }
    for(int i = 1; i <= m; i++){
        u = read(), v = read();
        g[u][v] = g[v][u] = 1;
    }
    floyed(n);
    s = read(), b = read(), k = read();
    for(int i = 1; i <= s; i++){
        shipos[i] = read(), atk[i] = read(), f[i] = read(), p[i] = read();
        id[i] = i;
    }
    sort(id+1, id+1+s, cmp);
    for(int i = 1; i <= b; i++){
        baspos[i] = read(), d[i] = read(), gold[i] = read();
        v1[baspos[i]].emplace_back(pii(d[i], gold[i]));
    }
    for(int i = 1; i <= k; i++){
        int tmp1, tmp2;
        tmp1 = read(), tmp2 = read();
        fuckacm[tmp1] = tmp2;
        in[tmp2]++, out[tmp1]++;
    }
    for(int i = 1; i <= n; i++){
        sort(v1[i].begin(), v1[i].end()); ps[i] = 0;
        for(int j = 1; j < v1[i].size(); j++){
            v1[i][j].second = max(v1[i][j].second, v1[i][j-1].second);
        }
    }
    for(int I = 1; I <= s; I++){
        int i = id[I];
        int ma = -INF;
        for(int j = 1; j <= n; j++){
            if(g[shipos[i]][j] <= f[i]){
                if(v1[j].empty()) continue;
                while(ps[j] < v1[j].size()-1 && v1[j][ps[j]+1].first <= atk[i]) ps[j]++;
                if(v1[j][ps[j]].first <= atk[i]) ma = max(ma, v1[j][ps[j]].second);
            }
        }
        val[i] = ma-p[i];
    }
    long long ans = 0;
    for(int I = 1; I <= s; I++){
        int i = id[I];
        if(in[i] == 0 && out[i] > 0 && !svis[i]){
            if(val[i] <= 0){
                svis[i] = true;
            }
        }
        if(in[i] == 0 && out[i] == 0 && val[i]>0 && !svis[i]){
            ans += val[i];
            svis[i] = true;
        }
        if(in[i] == 0 && out[i] == 0 && val[i] < 0 && !svis[i]){
            svis[i] = true;
        }
    }
    int S = 2015+1, T = S+1;
    init();
    for(int I = 1; I <= s; I++){
        int i = id[I];
        if(!svis[i]){
            if(val[i] > 0){
                num[i] = ++cnt;
                addedge(S, cnt, val[i]);
                ans += val[i];
            }
            else{
                num[i] = ++cnt;
                addedge(cnt, T, -val[i]);
            }
        }
    }
    for(int I = 1; I <= s; I++){
        int i = id[I];
        if(!svis[i] && val[i] > 0)
            addedge(num[i], num[fuckacm[i]], INF);
    }
    ans -= dinic(S, T, T+1);
    cout << ans;
    return 0;
}

#include <bits/stdc++.h>

using namespace std;

struct Dinic {
    //using F = int; const static F INF = 0x3f3f3f3f;
    using F = long long; const static F INF = 0x3f3f3f3f3f3f3f3f;
    struct Edge {
        int v, bro; F cap;
        Edge() {}
        Edge(int _v, int _bro, F _cap) : v(_v), bro(_bro), cap(_cap) {}
    };
    vector<Edge> e;
    vector<int> pos, cur;
    int n, s, t, m;
    Dinic(int _n, int _s, int _t) : n(_n), s(_s), t(_t), m(0) {
        pos.assign(n, -1);
        cur.resize(n);
        d.resize(n);
        e.reserve(4e5);
    }
    void add(int u, int v, F c=INF) {
        assert(u < n && v < n);
        e.emplace_back(v, pos[u], c); pos[u] = m++;
        e.emplace_back(u, pos[v], 0); pos[v] = m++;
    }
    vector<int> d;
    // build layer graph
    bool bfs() {
        fill(d.begin(), d.end(), -1);
        d[s] = 0;
        queue<int> q; q.push(s);
        while (!q.empty()) {
            int u = q.front(); q.pop();
            for (int i = cur[u] = pos[u]; i != -1; i = e[i].bro) {
                int v = e[i].v;
                if (d[v] == -1 && e[i].cap != 0) {
                    d[v] = d[u] + 1;
                    q.push(v);
                }
            }
        }
        return d[t] != -1;
    }
    // find blocking flow
    F dfs(int u, F lim) {
        if (u == t) return lim;
        F tot = 0;
        for (int& i = cur[u]; i != -1; i = e[i].bro) {
            int v = e[i].v;
            if (e[i].cap != 0 && d[v] == d[u] + 1) {
                F flow = dfs(v, min(e[i].cap, lim-tot));
                tot += flow;
                e[i].cap -= flow;
                e[i^1].cap += flow;
                if (tot == lim) return lim;
            }
        }
        return tot;
    }
    F flow() {
        F res = 0;
        while (bfs()) {
            res += dfs(s, INF);
        }
        return res;
    }
};

struct ProjectSelection {
    int n;
    int s,t;
    Dinic mc;
    using F = Dinic::F;
    ProjectSelection(int _n) : n(_n)
        , s(n)
        , t(n+1)
        , mc(n+2, s, t)
    {}

    void add_proj(int i, F profit) {
        if (profit >= 0) {
            mc.add(s, i, profit);
        } else {
            mc.add(i, t, -profit);
        }
    }

    // !!Caution: proj without dep-relation not included in flow
    // u,v: [0..n)
    void add_dep(int u, int v) {
        mc.add(u, v);
    }

    F profit() {
        return mc.flow();
    }
};

template <typename T=int>
struct Compress {
    map<T, int> id;
    vector<T> num;

    inline int get_id(T x) {
        if (!id.count(x)) {
            id[x] = num.size();
            num.emplace_back(x);
        }
        return id[x];
    }
    inline int get_num(int i) {
        assert(0 <= i && i < num.size());
        return num[i];
    }
};

struct ProjectSelectionDumper {
    using F = Dinic::F;
    F sum;
    ProjectSelectionDumper(const vector<F>& profits, const vector<pair<int, int>>& deps) {
        vector<bool> trk(profits.size(), false);
        Compress<int> c;
        for (auto& p: deps) {
            c.get_id(p.first);
            c.get_id(p.second);
            trk[p.first] = true;
            trk[p.second] = true;
        }

        ProjectSelection ps(c.num.size());
        sum = 0;
        for (int i = 0; i < (int)profits.size(); i++) {
            if (trk[i]) {
                ps.add_proj(c.get_id(i), profits[i]);
            } else if (profits[i] > 0) {
                sum += profits[i];
            }
        }
        for (auto& p: deps) {
            int u = c.get_id(p.first);
            int v = c.get_id(p.second);
            ps.add_dep(u, v);
        }
        sum += ps.profit();
    }
};

using ll=long long;
const int INF = 0x3f3f3f3f;
const int N = 111;
int d[N][N];

void solve() {
    int n,m;
    cin >> n >> m;
    memset(d, INF, sizeof d);
    for (int _ = 0; _ < m; _++) {
        int x,y;
        cin >> x >> y;
        x--;y--;
        d[x][y] = d[y][x] = 1;
    }
    for (int i = 0; i < n; i++) {
        d[i][i] = 0;
    }
    for (int k = 0; k < n; k++) {
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                if (d[i][k] < INF && d[k][j] < INF) {// for negative
                    d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
                }
            }
        }
    }

    int s,b,k;
    cin >> s >> b >> k;
    vector<int> x(s), a(s), f(s);
    vector<ll> p(s);
    for (int i = 0; i < s; i++) {
        cin >> x[i] >> a[i] >> f[i] >> p[i];
        --x[i];
    }
    vector<map<int,int>> dg(n);
    for (int _ = 0; _ < b; _++) {
        int i,d,g;
        cin >> i >> d >> g;
        i--;
        dg[i][d] = max(dg[i][d], g);
    }
    for (int i = 0; i < n; i++) {
        int pre = 0;
        for (auto it = dg[i].begin(); it != dg[i].end(); it++) {
            it->second = pre = max(it->second, pre);
        }
    }

    for (int i = 0; i < s; i++) {
        int mx = -1;
        int u = x[i];
        for (int j = 0; j < n; j++) {
            if (!dg[j].empty() && f[i] >= d[u][j]) {
                auto it = dg[j].upper_bound(a[i]);
                if (it != dg[j].begin()) {
                    --it;
                    mx = max(mx, it->second);
                }
            }
        }
        if (mx < 0) p[i] = -(1ll<<62);
        else p[i] = mx - p[i];
    }

    vector<pair<int, int>> deps;
    for (int _ = 0; _ < k; _++) {
        int u,v;
        cin >> u >> v;
        u--;v--;
        deps.emplace_back(u, v);
    }

    ProjectSelectionDumper ps(p, deps);

    cout << ps.sum << "\n";
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    solve();
    cout << endl;
}

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef ll F;
const int N    = 1e2 + 10;
const int maxs = 1e5 + 10;
const int maxn = 2e3 + 10;
const int maxm = 6e3 + 10;
const ll INF  = 2e13;
const F  INF_CAP = INF;

struct spaceship{
    int x,a,f,p;
}sp[maxs];
struct base {
    int d,g;
    bool operator < (const base& b)const {
        return d < b.d;
    }
};

ll best_goal[maxs];

vector<base> ba[N];
vector<int>  pre[N];
vector<int>  g[maxs];
bool used[maxs];
int w[N][N],id[maxs];

struct Dinic{
    int n,m,s,t,pos;
    int d[maxn],head[maxn],que[maxn],ptr[maxn];
    int to[maxm],nxt[maxm];
    F  cap[maxm];
    void init() {
        memset(head,-1,sizeof head);
    }
    void addedge(int a,int b,F c) {
//        printf("%d %d %lld\n",a,b,c);
//        printf("%d\n",m);
        cap[m] = c;to[m] = b;nxt[m] = head[a];head[a] = m++;
        cap[m] = 0;to[m] = a;nxt[m] = head[b];head[b] = m++;
    }
    bool bfs() {
        pos = 0;
        memset(d,-1,sizeof d);
        que[pos++] = s;
        d[s] = 0;
        for(int i = 0;i < pos;i++) {
            int x = que[i];
            for(int u = head[x];~u;u = nxt[u]) {
                if(d[to[u]] == -1&&cap[u]) {
                    d[to[u]] = d[x] + 1;
                    que[pos++] = to[u];
                }
            }
        }
        return d[t] != -1;
    }
    F dfs(int o,F mi) {
        if(o == t||mi == 0) return mi;
        F res = 0;
        for(int &x = ptr[o];~x;x = nxt[x]) if(d[to[x]] == d[o] + 1&&cap[x]){
            F tmp = dfs(to[x],min(mi,cap[x]));
            cap[x] -= tmp;
            cap[x^1] += tmp;
            mi -= tmp;
            res += tmp;
            if(mi == 0) return 0;
        }
        return res;
    }
    F maxflow(int s,int t) {
        this->s = s;this->t = t;
        F res = 0;
        while(bfs()) {
            memcpy(ptr,head,sizeof head);
            res += dfs(s,INF_CAP);
        }
        return res;
    }
}D;

int main() {
    D.init();
    int n,m,s,b,k;
    scanf("%d%d",&n,&m);
    for(int i = 1;i <= n;i++) fill(w[i] + 1,w[i] + 1 + n,n),w[i][i] = 0;
    for(int i = 0;i < m;i++) {
        int a,b;
        scanf("%d%d",&a,&b);
        w[b][a] = w[a][b] = min(w[a][b],1);
    }
    for(int d = 1;d <= n;d++) {
        for(int i = 1;i <= n;i++) {
            for(int j = 1;j <= n;j++) {
                w[i][j] = min(w[i][j],w[i][d] + w[d][j]);
            }
        }
    }
    scanf("%d%d%d",&s,&b,&k);
    for(int i = 1;i <= s;i++) {
        scanf("%d%d%d%d",&sp[i].x,&sp[i].a,&sp[i].f,&sp[i].p);
    }
    for(int i = 0;i < b;i++) {
        int x,d,g;
        scanf("%d%d%d",&x,&d,&g);
        ba[x].push_back(base{d,g});
    }
    for(int i = 1;i <= n;i++) if(ba[i].size()){
        int sz = (int)ba[i].size();
        sort(ba[i].begin(),ba[i].end());
        pre[i].resize(sz);
        pre[i][0] = ba[i][0].g;
        for(int j = 1;j < sz;j++) pre[i][j] = max(pre[i][j-1],ba[i][j].g);
    }
    for(int i = 1;i <= s;i++) {
        best_goal[i] = -INF_CAP;
        int x = sp[i].x;
        for(int j = 1;j <= n;j++) {
            if(w[x][j] <= sp[i].f) {
                int pos = upper_bound(ba[j].begin(),ba[j].end(),base{sp[i].a,0}) - ba[j].begin();
                --pos;
                if(pos >= 0) {
                    best_goal[i] = max(best_goal[i],(ll)pre[j][pos] - sp[i].p);
                }
            }
        }
    }
    for(int i = 0;i < k;i++) {
        int a,b;
        scanf("%d%d",&a,&b);
        g[a].push_back(b);
        used[a] = used[b] = 1;
    }
    ll ans = 0;
    int cnt = 0;
    for(int i = 1;i <= s;i++) {
        if(!used[i]) {
            if(best_goal[i] > 0) ans += best_goal[i];
        }
        else {
            id[i] = ++cnt;
        }
    }

    int st = 0,ed = cnt + 1;
    cnt = 0;
    for(int i = 1;i <= s;i++) {
        if(used[i]) {
            if(best_goal[i] >= 0) ans += best_goal[i],D.addedge(st,id[i],best_goal[i]);
            else D.addedge(id[i],ed,-best_goal[i]);
            for(auto& u:g[i]) D.addedge(id[i],id[u],INF_CAP);
        }
    }
    // printf("%lld\n",ans);
    ans -= D.maxflow(st,ed);
    printf("%lld\n",ans);
    return 0;
}

#include <bits/stdc++.h>
//
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 100015;
const int maxm = 1000005;
int g[105][105];
int num[maxn];
int cnt;
void floyed(int n){
    for(int k = 1; k <= n; k++){
        for(int i = 1; i <= n; i++){
            for(int j = 1; j <= n; j++){
                g[i][j] = min(g[i][j], g[i][k]+g[k][j]);
            }
        }
    }
};
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
    while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
struct Edge{
    int to,next,cap,flow;
}edge[maxm];
int tol,head[maxn];
void init()
{
    tol=2;
    memset(head,-1,sizeof(head));
}
void addedge(int u,int v,int w,int rw=0)
{
    edge[tol].to=v;edge[tol].cap=w;edge[tol].flow=0;
    edge[tol].next=head[u];head[u]=tol++;
    edge[tol].to=u;edge[tol].cap=rw;edge[tol].flow=0;
    edge[tol].next=head[v];head[v]=tol++;
}
int Q[maxn];
int dep[maxn],cur[maxn],sta[maxn];
bool bfs(int s,int t,int n)
{
    int front=0,tail=0;
    memset(dep,-1,sizeof(dep[0])*(n+1));
    dep[s]=0;
    Q[tail++]=s;
    while(front<tail){
        int u=Q[front++];
        for(int i=head[u];i!=-1;i=edge[i].next){
            int v=edge[i].to;
            if(edge[i].cap>edge[i].flow&&dep[v]==-1){
                dep[v]=dep[u]+1;
                if(v==t){
                    return true;
                }
                Q[tail++]=v;
            }
        }
    }
    return false;
}
long long dinic(int s,int t,int n)
{
    long long maxflow=0;
    while(bfs(s,t,n)){
        for(int i=0;i<n;i++){
            cur[i]=head[i];
        }
        int u=s,tail=0;
        while(cur[s]!=-1){
            if(u==t){
                int tp=INF;
                for(int i=tail-1;i>=0;i--){
                    tp=min(tp,edge[sta[i]].cap-edge[sta[i]].flow);
                }
                maxflow+=tp;
                for(int i=tail-1;i>=0;i--){
                    edge[sta[i]].flow+=tp;
                    edge[sta[i]^1].flow-=tp;
                    if(edge[sta[i]].cap-edge[sta[i]].flow==0){
                        tail=i;
                    }
                }
                u=edge[sta[tail]^1].to;
            }else if(cur[u]!=-1&&edge[cur[u]].cap>edge[cur[u]].flow&&dep[u]+1==dep[edge[cur[u]].to]){
                sta[tail++]=cur[u];
                u=edge[cur[u]].to;
            }else{
                while(u!=s&&cur[u]==-1){
                    u=edge[sta[--tail]^1].to;
                }
                cur[u]=edge[cur[u]].next;
            }
        }
    }
    return maxflow;
}
//vector<int>fuck[100005];
int fuckacm[100005];
int ps[105];
int in[maxn], out[maxn], shipos[maxn], atk[maxn], f[maxn], p[maxn], baspos[maxn], d[maxn], gold[maxn], val[maxn];
bool svis[maxn];
#define pii pair<int,int>
vector<pii> v1[105];
int main(){
    int n, m, u, v, s, b, k;
    n = read(), m = read();
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n; j++){
            if(i==j) g[i][j] = 0;
            else g[i][j] = g[j][i] = INF;
        }
    }
    for(int i = 1; i <= m; i++){
        u = read(), v = read();
        g[u][v] = g[v][u] = 1;
    }
    floyed(n);
    s = read(), b = read(), k = read();
    for(int i = 1; i <= s; i++){
        shipos[i] = read(), atk[i] = read(), f[i] = read(), p[i] = read();
    }
    for(int i = 1; i <= b; i++){
        baspos[i] = read(), d[i] = read(), gold[i] = read();
        v1[baspos[i]].emplace_back(pii(d[i], gold[i]));
    }
    for(int i = 1; i <= k; i++){
        int tmp1, tmp2;
        tmp1 = read(), tmp2 = read();
        fuckacm[tmp1] = tmp2;
        in[tmp2]++, out[tmp1]++;
    }
    for(int i = 1; i <= s; i++){
        int ma = -INF;
        for(int j = 1; j <= n; j++){
            if(g[shipos[i]][j] <= f[i]){
                if(v1[j].empty()) continue;
                while(ps[j] < v1[j].size()-1 && v1[j][ps[j]+1].first <= atk[i]) ps[j]++;
                if(v1[j][ps[j]].first <= atk[i]) ma = max(ma, v1[j][ps[j]].second);
            }
        }
        val[i] = ma-p[i];
    }
    long long ans = 0;
    for(int i = 1; i <= s; i++){
        if(in[i] == 0 && out[i] > 0){
            if(val[i] <= 0){
                svis[i] = true;
            }
        }
        if(in[i] == 0 && out[i] == 0 && val[i]>0){
            ans += val[i];
            svis[i] = true;
        }
        if(in[i] == 0 && out[i] == 0 && val[i] < 0){
            svis[i] = true;
        }
    }
    int S = 2015+1, T = S+1;
    init();
    for(int i = 1; i <= s; i++){
        if(!svis[i]){
            if(val[i] > 0){
                num[i] = ++cnt;
                addedge(S, cnt, val[i]);
                ans += val[i];
            }
            else{
                num[i] = ++cnt;
                addedge(cnt, T, -val[i]);
            }
        }
    }
    for(int i = 1; i <= s; i++){
        if(!svis[i] && val[i] > 0)
            addedge(num[i], num[fuckacm[i]], INF);
    }
    ans -= dinic(S, T, T+1);
    cout << ans;
    return 0;
}

#include <algorithm>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>
#define debug(...) fprintf(stderr, __VA_ARGS__)
using namespace std;
inline char nc()
{
    return getchar();
	static char buf[100000], *l = buf, *r = buf;
	return l==r&&(r=(l=buf)+fread(buf,1,100000,stdin),l==r)?EOF:*l++;
}
template<class T> void read(T &x)
{
	x = 0; int f = 1, ch = nc();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=nc();}
	while(ch>='0'&&ch<='9'){x=x*10-'0'+ch;ch=nc();}
	x *= f;
}
typedef long long ll;
const int inf = 1e9 + 1;
const int maxn = 100 + 5;
const int maxs = 1e5 + 5;
const int maxb = 1e5 + 5;
int n, m;
int s, b, k;
int st, ed;
int val[maxn];
int dis[maxn][maxn];
int head[maxs];
vector<int> adj[maxn];
struct data
{
    int a, b, c, d, id;
    inline bool operator < (const data &other) const
    {
        return b < other.b;
    }
} A[maxs], B[maxb];
struct edge
{
    int to, nex, cap, flow;
    edge(int to=0,int nex=0,int cap=0,int flow=0):to(to),nex(nex),cap(cap),flow(flow){}
};
vector<edge> G;
inline void adde(int u, int v)
{
    adj[u].push_back(v);
    adj[v].push_back(u);
}
inline void addedge(int u, int v, int c)
{
    G.push_back(edge(v, head[u], c, 0)), head[u] = G.size() - 1;
    G.push_back(edge(u, head[v], 0, 0)), head[v] = G.size() - 1;
}
namespace dinic
{
    int dis[maxs], cur[maxs];
    bool BFS()
    {
        static int q[maxs];
        int hd = 0, tl = 0;
        memset(dis, -1, sizeof(dis));
        dis[st] = 0;
        q[tl++] = st;
        while(hd < tl)
        {
            int u = q[hd++];
            for(int i = head[u]; ~i; i = G[i].nex)
            {
                int v = G[i].to;
                if(dis[v] == -1 && G[i].cap != G[i].flow)
                {
                    dis[v] = dis[u] + 1;
                    q[tl++] = v;
                }
            }
        }
        return dis[ed] != -1;
    }
    ll DFS(int u, ll flow)
    {
        if(u == ed || flow == 0) return flow;
        ll rec = flow;
        for(int &i = cur[u]; ~i; i = G[i].nex)
        {
            int v = G[i].to;
            if(dis[v] == dis[u] + 1)
            {
                ll d = DFS(v, min(flow, (ll)G[i].cap - G[i].flow));
                G[i].flow += d;
                G[i ^ 1].flow -= d;
                flow -= d;
                if(flow == 0) break;
            }
        }
        return rec - flow;
    }
    ll maxflow()
    {
        ll flow = 0;
        while(BFS())
        {
            memcpy(cur, head, sizeof(head));
            flow += DFS(st, 1e18);
        }
        return flow;
    }
}
int adde(int x)
{
    int mx = 0;
    for(int i = 1; i <= n; ++i) if(dis[ A[x].a ][i] <= A[x].c)
    {
        mx = max(mx, val[i]);
    }
    mx -= A[x].d;
    if(mx < 0)
    {
        addedge(A[x].id, ed, -mx);
        return 0;
    }
    addedge(st, A[x].id, mx);
    return mx;
}
void BFS(int st)
{
    static int q[maxn];
    int hd = 0, tl = 0;
    for(int i = 1; i <= n; ++i) dis[st][i] = inf;
    dis[st][st] = 0;
    q[tl++] = st;
    while(hd < tl)
    {
        int u = q[hd++];
        for(unsigned int i = 0; i < adj[u].size(); ++i)
        {
            int v = adj[u][i];
            if(dis[st][v] == inf)
            {
                dis[st][v] = dis[st][u] + 1;
                q[tl++] = v;
            }
        }
    }
}
void init()
{
    for(int i = 1; i <= n; ++i) BFS(i);
}
ll solve()
{
    init();
    sort(A + 1, A + s + 1);
    sort(B + 1, B + b + 1);
    ll an = 0;
    int i = 1, j = 1;
    st = 0, ed = s + 1;
    while(i <= s && j <= b)
    {
        if(B[j].b <= A[i].b)
        {
            val[ B[j].a ] = max(val[ B[j].a ], B[j].c);
            ++j;
        }
        else
        {
            an += adde(i++);
        }
    }
    while(i <= s) an += adde(i++);
    return an - dinic :: maxflow();
}
int main()
{
    read(n), read(m);
    for(int i = 1; i <= m; ++i)
    {
        int u, v; read(u), read(v);
        adde(u, v);
    }
    read(s), read(b), read(k);
    for(int i = 1; i <= s; ++i)
    {
        read(A[i].a), read(A[i].b), read(A[i].c), read(A[i].d);
        A[i].id = i;
    }
    for(int i = 1; i <= b; ++i)
    {
        read(B[i].a), read(B[i].b), read(B[i].c);
    }
    memset(head, -1, sizeof(head));
    for(int i = 1; i <= k; ++i)
    {
        int s1, s2; read(s1), read(s2);
        addedge(s1, s2, inf);
    }
    printf("%I64d\n", solve());
    return 0;
}

#include <bits/stdc++.h>
using namespace std;
int n, m;
int tav[109][109];
int s, b, KK;
int legjobb[109][109]; // csucs, tav
long long profit[100009];
long long infi=1e15;
struct BaseShip
{
    int lo;
    int pwr;
    int fuel;
    int cost;
    int tp;
    int idx;
    bool operator<(const BaseShip & BS) const
    {
        if(pwr==BS.pwr)
        {
            return tp<BS.tp;
        }
        return pwr<BS.pwr;
    }
};
vector<BaseShip> t;
void javit(BaseShip & BS)
{
    for(int i=1; i<=n; i++)
    {
        if(tav[i][BS.lo]>=0)
        {
            legjobb[i][tav[i][BS.lo]]=max(legjobb[i][tav[i][BS.lo]], BS.cost);
        }
    }
}
long long ertek(BaseShip & BS)
{
    long long ret=-infi;
    for(int dd=0; dd<=min(n-1, BS.fuel); dd++)
    {
        ret=max(ret, (long long)legjobb[BS.lo][dd]);
    }
    return ret;
}
vector<int> G[100009];
vector<long long> cap[100009];
vector<long long> flow[100009];
vector<int> holvan[100009];
int bejar[100009];
int bejarszam;
int apa[100009];
int apael[100009];
long long profitsum=0;
int sor[100009];
long long FF()
{
    long long ret=0;
    int start=0;
    int sk;
    int sv;
    while(1)
    {
        sk=1;
        sv=1;
        sor[1]=start;
        bejarszam++;
        bejar[start]=bejarszam;
        apa[start]=-1;
        apael[start]=-1;
        while(sk<=sv)
        {
            int akt=sor[sk];
            for(int i=0; i<G[akt].size(); i++)
            {
                int sz=G[akt][i];
                long long cc=cap[akt][i];
                if(bejar[sz]==bejarszam) continue;
                if(cc==flow[akt][i]) continue;
                sv++;
                sor[sv]=sz;
                apa[sz]=akt;
                apael[sz]=i;
                bejar[sz]=bejarszam;
            }
            sk++;
        }
        if(bejar[s+1]<bejarszam) break;
        long long maxpush=infi;
        int akt=s+1;
        while(akt!=0)
        {
            if(cap[apa[akt]][apael[akt]]==0)
            {
                maxpush=min(maxpush, flow[apa[akt]][apael[akt]]);
            }
            else
            {
                maxpush=min(maxpush, cap[apa[akt]][apael[akt]]-flow[apa[akt]][apael[akt]]);
            }
            //cout<<akt<<"->";
            akt=apa[akt];
        }
        //cout<<endl;
        akt=s+1;
        while(akt!=0)
        {
            //at kell irni a folyamot
            if(cap[apa[akt]][apael[akt]]==0)
            {
                flow[apa[akt]][apael[akt]]-=maxpush;
                flow[akt][holvan[apa[akt]][apael[akt]]]-=maxpush;
            }
            else
            {
                flow[apa[akt]][apael[akt]]+=maxpush;
                flow[akt][holvan[apa[akt]][apael[akt]]]+=maxpush;
            }
            akt=apa[akt];
        }
        ret+=maxpush;
    }
    return ret;
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cin>>n>>m;
    for(int i=1; i<=n; i++)
    {
        for(int j=1; j<=n; j++)
        {
            tav[i][j]=-1;
        }
        tav[i][i]=0;
    }
    for(int i=1; i<=m; i++)
    {
        int a, b;
        cin>>a>>b;
        if(a!=b)
        {
            tav[a][b]=1;
            tav[b][a]=1;
        }
    }
    for(int k=1; k<=n; k++)
    {
        for(int i=1; i<=n; i++)
        {
            for(int j=1; j<=n; j++)
            {
                if(tav[i][k]>=0 && tav[k][j]>=0)
                {
                    if(tav[i][j]==-1 || tav[i][j]>tav[i][k]+tav[k][j]) tav[i][j]=tav[i][k]+tav[k][j];
                }
            }
        }
    }
    cin>>s>>b>>KK;
    t.resize(s+b);
    for(int i=0; i<s; i++)
    {
        cin>>t[i].lo>>t[i].pwr>>t[i].fuel>>t[i].cost;
        t[i].tp=1;
        t[i].idx=i+1;
    }
    for(int i=s; i<s+b; i++)
    {
        cin>>t[i].lo>>t[i].pwr>>t[i].cost;
        t[i].tp=0;
    }
    sort(t.begin(), t.end());
    for(int i=0; i<t.size(); i++)
    {
        if(t[i].tp==0)
        {
            javit(t[i]);
        }
        else
        {
            profit[t[i].idx]=ertek(t[i])-t[i].cost;
            if(profit[t[i].idx]>=0)
            {
                profitsum+=profit[t[i].idx];
            }
        }
    }
    for(int i=1; i<=KK; i++)
    {
        int s1, s2;
        cin>>s1>>s2;
        if(s1==s2) continue;
        holvan[s1].push_back(G[s2].size());
        holvan[s2].push_back(G[s1].size());
        G[s1].push_back(s2);
        G[s2].push_back(s1);
        cap[s1].push_back(infi);
        cap[s2].push_back(0);
        flow[s1].push_back(0);
        flow[s2].push_back(0);
    }
    for(int i=1; i<=s; i++)
    {
        if(G[i].size()==0) continue;
        if(profit[i]>=0)
        {
            holvan[0].push_back(G[i].size());
            holvan[i].push_back(G[0].size());
            G[0].push_back(i);
            G[i].push_back(0);
            cap[0].push_back(profit[i]);
            cap[i].push_back(0);
            flow[0].push_back(0);
            flow[i].push_back(0);
        }
        else
        {
            holvan[s+1].push_back(G[i].size());
            holvan[i].push_back(G[s+1].size());
            G[s+1].push_back(i);
            G[i].push_back(s+1);
            cap[s+1].push_back(0);
            cap[i].push_back(-profit[i]);
            flow[s+1].push_back(0);
            flow[i].push_back(0);
        }
    }
    /*for(int i=1; i<=s; i++)
    {
        cout<<profit[i]<<" --profit"<<endl;
    }
    for(int i=0; i<=s+1; i++)
    {
        for(int j=0; j<G[i].size(); j++)
        {
            int sz=G[i][j];
            cout<<i<<" --- "<<sz<<" cap: "<<cap[i][j]<<" folyam: "<<flow[i][j]<<endl;
        }
    }*/
    long long mincut=FF();
    //cout<<"mincut: "<<mincut<<endl;
    cout<<profitsum-mincut<<endl;
    return 0;
}

#pragma GCC optimize("Ofast")
/*#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("fast-math")
#pragma GCC target("sse,sse2,sse3,ssse3,popcnt,abm,mmx,tune=native")*/
#include <iostream>
#include <vector>
#include <algorithm>
#include <set>
#include <map>
#include <unordered_set>
#include <unordered_map>
#include <stdio.h>
#include <cstdio>
#include <math.h>
#include <cmath>
#include <string>
#include <cstring>
#include <queue>
#include <deque>
#include <random>
#include <iomanip>
#include <bitset>

using namespace std;

template<typename T> void uin(T &a, T b) {
    if (b < a) {
        a = b;
    }
}

template<typename T> void uax(T &a, T b) {
    if (b > a) {
        a = b;
    }
}

#define int long long
#define ghost signed
#define left left228
#define right right228
#define prev prev228
#define list list228

const int INF = 1e15;

namespace Dinic
{
	const int N = 100 * 1000 + 228;

	struct edge
	{
		int from, to, cap, flow;

		int rem() {
			return cap - flow;
		}

		edge() {}
		edge(int _from, int _to, int _cap, int _flow) {
			from = _from;
			to = _to;
			cap = _cap;
			flow = _flow;
		}
	};

	int n;
	vector<int> g[N];
	int fir[N], d[N];
	vector< edge > e;
	int F = 0;

	void add_edge(int u, int v, int c) {
		g[u].push_back((int)e.size());
		e.push_back(edge(u, v, c, 0LL));
		g[v].push_back((int)e.size());
		e.push_back(edge(v, u, 0LL, 0LL));
	}

	bool bfs(int s, int t) {
		for (int i = 1; i <= n; ++i) d[i] = INF;
		d[s] = 0;
		vector<int> q;
		q.push_back(s);
		for (int i = 0; i < (int)q.size(); ++i) {
			int v = q[i];
			for (int num : g[v]) {
				int to = e[num].to;
				if (e[num].rem() && d[v] + 1 < d[to]) {
					d[to] = d[v] + 1;
					q.push_back(to);
				}
			}
		}
		return d[t] != INF;
	}

	int dfs(int v, int t, int c = INF) {
		if (v == t) {
			F += c;
			return c;
		}
		for (; fir[v] < (int)g[v].size(); ++fir[v]) {
			int i = g[v][fir[v]];
			int to = e[i].to;
			if (d[v] + 1 == d[to] && e[i].rem()) {
				int x = dfs(to, t, min(c, e[i].rem()));
				if (x) {
					e[i].flow += x;
					e[i ^ 1].flow -= x;
					return x;
				}
			}
		}
		return 0;
	}

	int max_flow(int s, int t) {
		F = 0;
		while (bfs(s, t)) {
			for (int i = 1; i <= n; ++i) fir[i] = 0;
			while (dfs(s, t)) ;
		}
		return F;
	}
};

const int N = 105;

struct SHIP
{
	int x, a, f, p;
	SHIP() {}
	SHIP(int _x, int _a, int _f, int _p) {
		x = _x, a = _a, f = _f, p = _p;
	}
};

SHIP ship[N * 1000];

int d[N][N];
int value[N * 1000];
vector< pair<int, int> > list[N * 1000];

ghost main() {
	ios_base::sync_with_stdio(false);
	cin.tie(0);
	int n, m;
	cin >> n >> m;
	for (int i = 1; i <= n; ++i) {
		for (int j = 1; j <= n; ++j) {
			d[i][j] = INF;
		}
		d[i][i] = 0;
	}
	for (int i = 0; i < m; ++i) {
		int u, v;
		cin >> u >> v;
		d[u][v] = d[v][u] = 1;
	}
	for (int k = 1; k <= n; ++k) {
		for (int i = 1; i <= n; ++i) {
			for (int j = 1; j <= n; ++j) {
				if (d[i][k] != INF && d[k][j] != INF) {
					uin(d[i][j], d[i][k] + d[k][j]);
				}
			}
		}
	}
	int s, b, k;
	cin >> s >> b >> k;
	for (int i = 1; i <= s; ++i) {
		cin >> ship[i].x >> ship[i].a >> ship[i].f >> ship[i].p;
	}
	for (int i = 1; i <= b; ++i) {
		int x, d, g;
		cin >> x >> d >> g;
		list[x].push_back(make_pair(d, g));
	}
	for (int i = 1; i <= n; ++i) {
		sort(list[i].begin(), list[i].end());
		for (int j = 1; j < (int)list[i].size(); ++j) {
			uax(list[i][j].second, list[i][j - 1].second);
		}
	}
	for (int i = 1; i <= s; ++i) {
		bool ok = 0;
		for (int v = 1; v <= n; ++v) {
			if (d[ship[i].x][v] > ship[i].f || list[v].empty()) continue;
			int l = 0, r = (int)list[v].size();
			while (r - l > 1) {
				int mid = (l + r) >> 1;
				if (list[v][mid].first <= ship[i].a) {
					l = mid;
				} else {
					r = mid;
				}
			}
			if (list[v][l].first <= ship[i].a) {
				uax(value[i], list[v][l].second);
				ok = 1;
			}
		}
		if (!ok) value[i] = -INF;
	}
	for (int i = 1; i <= n; ++i) {
		if (value[i] != -INF) value[i] -= ship[i].p;
	}
	Dinic::n = s + 2;
	for (int i = 0; i < k; ++i) {
		int u, v;
		cin >> u >> v;
		Dinic::add_edge(u, v, INF);
	}
	int S = s + 1, T = s + 2;
	int sumpos = 0;
	for (int i = 1; i <= s; ++i) {
		if (value[i] > 0) {
			Dinic::add_edge(S, i, value[i]);
			sumpos += value[i];
		} else {
			Dinic::add_edge(i, T, -value[i]);
		}
	}
	int res = sumpos - Dinic::max_flow(S, T);
	cout << res << '\n';
	return 0;
} // kek ;

#include <bits/stdc++.h>
//
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 100015;
const int maxm = 1000005;
int g[105][105];
int num[maxn];
int cnt;
void floyed(int n){
    for(int k = 1; k <= n; k++){
        for(int i = 1; i <= n; i++){
            for(int j = 1; j <= n; j++){
                g[i][j] = min(g[i][j], g[i][k]+g[k][j]);
            }
        }
    }
};
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
    while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
struct Edge{
    int to,next,cap,flow;
}edge[maxm];
int tol,head[maxn];
void init()
{
    tol=2;
    memset(head,-1,sizeof(head));
}
void addedge(int u,int v,int w,int rw=0)
{
    edge[tol].to=v;edge[tol].cap=w;edge[tol].flow=0;
    edge[tol].next=head[u];head[u]=tol++;
    edge[tol].to=u;edge[tol].cap=rw;edge[tol].flow=0;
    edge[tol].next=head[v];head[v]=tol++;
}
int Q[maxn];
int dep[maxn],cur[maxn],sta[maxn];
bool bfs(int s,int t,int n)
{
    int front=0,tail=0;
    memset(dep,-1,sizeof(dep[0])*(n+1));
    dep[s]=0;
    Q[tail++]=s;
    while(front<tail){
        int u=Q[front++];
        for(int i=head[u];i!=-1;i=edge[i].next){
            int v=edge[i].to;
            if(edge[i].cap>edge[i].flow&&dep[v]==-1){
                dep[v]=dep[u]+1;
                if(v==t){
                    return true;
                }
                Q[tail++]=v;
            }
        }
    }
    return false;
}
long long dinic(int s,int t,int n)
{
    long long maxflow=0;
    while(bfs(s,t,n)){
        for(int i=0;i<n;i++){
            cur[i]=head[i];
        }
        int u=s,tail=0;
        while(cur[s]!=-1){
            if(u==t){
                int tp=INF;
                for(int i=tail-1;i>=0;i--){
                    tp=min(tp,edge[sta[i]].cap-edge[sta[i]].flow);
                }
                maxflow+=tp;
                for(int i=tail-1;i>=0;i--){
                    edge[sta[i]].flow+=tp;
                    edge[sta[i]^1].flow-=tp;
                    if(edge[sta[i]].cap-edge[sta[i]].flow==0){
                        tail=i;
                    }
                }
                u=edge[sta[tail]^1].to;
            }else if(cur[u]!=-1&&edge[cur[u]].cap>edge[cur[u]].flow&&dep[u]+1==dep[edge[cur[u]].to]){
                sta[tail++]=cur[u];
                u=edge[cur[u]].to;
            }else{
                while(u!=s&&cur[u]==-1){
                    u=edge[sta[--tail]^1].to;
                }
                cur[u]=edge[cur[u]].next;
            }
        }
    }
    return maxflow;
}
//vector<int>fuck[100005];
int fuckacm[100005];
int ps[105];
int in[maxn], out[maxn], shipos[maxn], atk[maxn], f[maxn], p[maxn], baspos[maxn], d[maxn], gold[maxn], val[maxn];
bool svis[maxn];
#define pii pair<int,int>
vector<pii> v1[105];
int main(){
    int n, m, u, v, s, b, k;
    n = read(), m = read();
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n; j++){
            if(i==j) g[i][j] = 0;
            else g[i][j] = g[j][i] = INF;
        }
    }
    for(int i = 1; i <= m; i++){
        u = read(), v = read();
        g[u][v] = g[v][u] = 1;
    }
    floyed(n);
    s = read(), b = read(), k = read();
    for(int i = 1; i <= s; i++){
        shipos[i] = read(), atk[i] = read(), f[i] = read(), p[i] = read();
    }
    for(int i = 1; i <= b; i++){
        baspos[i] = read(), d[i] = read(), gold[i] = read();
        v1[baspos[i]].emplace_back(pii(d[i], gold[i]));
    }
    for(int i = 1; i <= k; i++){
        int tmp1, tmp2;
        tmp1 = read(), tmp2 = read();
        fuckacm[tmp1] = tmp2;
        in[tmp2]++, out[tmp1]++;
    }
    for(int i = 1; i <= n; i++){
        sort(v1[i].begin(), v1[i].end()); ps[i] = 0;
        for(int j = 1; j < v1[i].size(); j++){
            v1[i][j].second = max(v1[i][j].second, v1[i][j-1].second);
        }
    }
    for(int i = 1; i <= s; i++){
        int ma = -INF;
        for(int j = 1; j <= n; j++){
            if(g[shipos[i]][j] <= f[i]){
                if(v1[j].empty()) continue;
                while(ps[j] < v1[j].size()-1 && v1[j][ps[j]+1].first <= atk[i]) ps[j]++;
                if(v1[j][ps[j]].first <= atk[i]) ma = max(ma, v1[j][ps[j]].second);
            }
        }
        val[i] = 0-p[i];
    }
    long long ans = 0;
    for(int i = 1; i <= s; i++){
        if(in[i] == 0 && out[i] > 0 && !svis[i]){
            if(val[i] <= 0){
                svis[i] = true;
            }
        }
        if(in[i] == 0 && out[i] == 0 && val[i]>0 && !svis[i]){
            ans += val[i];
            svis[i] = true;
        }
        if(in[i] == 0 && out[i] == 0 && val[i] < 0 && !svis[i]){
            svis[i] = true;
        }
    }
    int S = 2015+1, T = S+1;
    init();
    for(int i = 1; i <= s; i++){
        if(!svis[i]){
            if(val[i] > 0){
                num[i] = ++cnt;
                addedge(S, cnt, val[i]);
                ans += val[i];
            }
            else{
                num[i] = ++cnt;
                addedge(cnt, T, -val[i]);
            }
        }
    }
    for(int i = 1; i <= s; i++){
        if(!svis[i] && val[i] > 0)
            addedge(num[i], num[fuckacm[i]], INF);
    }
    ans -= dinic(S, T, T+1);
    cout << ans;
    return 0;
}

#include <iostream>
#include <algorithm>
#include <vector>
#include <map>

#define X first
#define Y second

using namespace std;

const int maxn = 2020;
const int inf = 1e9 + 7;

struct edge {
	int a, b, cap, flow;
	edge(int a, int b, int cap) : a(a), b(b), cap(cap), flow(0) {}
};

int S = 0, T, dist[maxn], q[maxn], ptr[maxn];
vector<edge> e;
vector<int> g[maxn];

void add_edge(int a, int b, int cap) {
	g[a].push_back((int)e.size());
	e.push_back(edge(a, b, cap));
	g[b].push_back((int)e.size());
	e.push_back(edge(b, a, 0));
}

bool bfs() {
	fill(dist, dist + maxn, -1);
	dist[S] = 0;
	int qh = 0, qt = 0;
	q[qt++] = S;
	while(qh < qt and dist[T] == -1) {
		int v = q[qh++];
		for(int id : g[v]) {
			if(dist[e[id].b] == -1 and e[id].flow < e[id].cap) {
				q[qt++] = e[id].b;
				dist[e[id].b] = dist[v] + 1;
			}
		}
	}
	return dist[T] != -1;
}

int dfs(int v, int flow) {
	if(flow == 0) return 0;
	if(v == T) return flow;
	for(; ptr[v] < g[v].size(); ptr[v]++) {
		int id = g[v][ptr[v]];
		if(dist[e[id].b] != dist[v] + 1) continue;
		int pushed = dfs(e[id].b, min(flow, e[id].cap - e[id].flow));
		if(pushed) {
			e[id].flow += pushed;
			e[id ^ 1].flow -= pushed;
			return pushed;
		}
	}
	return 0;
}

long long dinic() {
	long long flow = 0;
	while(bfs()) {
		fill(ptr, ptr + maxn, 0);
		while(int pushed = dfs(S, inf)) flow += pushed;
	}
	return flow;
}

int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	int n, m;
	cin >> n >> m;
	int d[n + 1][n + 1];
	for(int i = 1; i <= n; i++) {
		for(int j = 1; j <= n; j++) {
			d[i][j] = d[j][i] = inf;
		}
		d[i][i] = 0;
	}
	for(int i = 0; i < m; i++) {
		int u, v;
		cin >> u >> v;
		if(u != v) {
			d[u][v] = d[v][u] = 1;
		}
	}
	for(int k = 1; k <= n; k++) {
		for(int i = 1; i <= n; i++) {
			for(int j = 1; j <= n; j++) {
				d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
			}
		}
	}
	int s, b, k;
	cin >> s >> b >> k;
	long long spos[s], attack[s], fuel[s], price[s];
	long long bpos[b], defense[b], gold[b];
	for(int i = 0; i < s; i++) {
		cin >> spos[i] >> attack[i] >> fuel[i] >> price[i];
	}
	for(int i = 0; i < b; i++) {
		cin >> bpos[i] >> defense[i] >> gold[i];
	}
	bool indep[s] = {0};
	pair<int, int> dep[k];
	for(int i = 0; i < k; i++) {
		cin >> dep[i].X >> dep[i].Y;
		indep[dep[i].X - 1] = indep[dep[i].Y - 1] = true;
	}
	vector<pair<long long, long long> > maxpref[n + 1];
	for(int i = 1; i <= n; i++) {
		maxpref[i].push_back({0, -2 * inf});
	}
	for(int i = 0; i < b; i++) {
		maxpref[bpos[i]].push_back({defense[i], gold[i]});
	}
	for(int i = 1; i <= n; i++) {
		sort(maxpref[i].begin(), maxpref[i].end());
		for(int j = 1; j < maxpref[i].size(); j++) {
			maxpref[i][j].Y = max(maxpref[i][j].Y, maxpref[i][j - 1].Y);
		}
	}
	long long maxprofit[s];
	for(int i = 0; i < s; i++) {
		long long ans = -inf * 2;
		for(int j = 1; j <= n; j++) {
			if(d[spos[i]][j] <= fuel[i]) {
				int x = upper_bound(maxpref[j].begin(), maxpref[j].end(), make_pair(attack[i], 0ll)) - maxpref[j].begin();
				ans = max(ans, 1ll * maxpref[j][x - 1].Y - price[i]);
			}
		}
		maxprofit[i] = ans;
	}
	int nxt = 1;
	int newnum[s];
	for(int i = 0; i < s; i++) {
		if(indep[i]) newnum[i] = nxt++;
	}
	T = nxt;
	for(int i = 0; i < s; i++) {
		if(indep[i]) {
			if(maxprofit[i] > 0) add_edge(S, newnum[i], maxprofit[i]);
			else if(maxprofit[i] != -inf * 2) add_edge(newnum[i], T, -maxprofit[i]);
		}
	}
	for(int i = 0; i < k; i++) {
		add_edge(newnum[dep[i].X - 1], newnum[dep[i].Y - 1], 2 * inf);
	}
	long long ans = 0;
	for(int i = 0; i < s; i++) {
		if(maxprofit[i] > 0) ans += maxprofit[i];
	}
	cout << ans - dinic() << '\n';
	return 0;
}

//Author: Heltion
//Date: 07-31-2019
#include<bits/stdc++.h>
using namespace std;
using LL = long long;
template<typename T>void no(T s){cout << s; exit(0);}
void no(){cout << "NO"; exit(0);}
constexpr LL maxm = 120;
constexpr LL maxn = 120000;
LL d[maxm][maxm];
LL sx[maxn], a[maxn], f[maxn], p[maxn], bx[maxn], dd[maxn], g[maxn];
struct FlowEdge {
    int v, u;
    long long cap, flow = 0;
    FlowEdge(int v, int u, long long cap) : v(v), u(u), cap(cap) {}
};

struct Dinic {
    const long long flow_inf = 1e18;
    vector<FlowEdge> edges;
    vector<vector<int>> adj;
    int n, m = 0;
    int s, t;
    vector<int> level, ptr;
    queue<int> q;

    Dinic(int n, int s, int t) : n(n), s(s), t(t) {
        adj.resize(n);
        level.resize(n);
        ptr.resize(n);
    }

    void add_edge(int v, int u, long long cap) {
        edges.emplace_back(v, u, cap);
        edges.emplace_back(u, v, 0);
        adj[v].push_back(m);
        adj[u].push_back(m + 1);
        m += 2;
    }

    bool bfs() {
        while (!q.empty()) {
            int v = q.front();
            q.pop();
            for (int id : adj[v]) {
                if (edges[id].cap - edges[id].flow < 1)
                    continue;
                if (level[edges[id].u] != -1)
                    continue;
                level[edges[id].u] = level[v] + 1;
                q.push(edges[id].u);
            }
        }
        return level[t] != -1;
    }

    long long dfs(int v, long long pushed) {
        if (pushed == 0)
            return 0;
        if (v == t)
            return pushed;
        for (int& cid = ptr[v]; cid < (int)adj[v].size(); cid++) {
            int id = adj[v][cid];
            int u = edges[id].u;
            if (level[v] + 1 != level[u] || edges[id].cap - edges[id].flow < 1)
                continue;
            long long tr = dfs(u, min(pushed, edges[id].cap - edges[id].flow));
            if (tr == 0)
                continue;
            edges[id].flow += tr;
            edges[id ^ 1].flow -= tr;
            return tr;
        }
        return 0;
    }

    long long flow() {
        long long f = 0;
        while (true) {
            fill(level.begin(), level.end(), -1);
            level[s] = 0;
            q.push(s);
            if (!bfs())
                break;
            fill(ptr.begin(), ptr.end(), 0);
            while (long long pushed = dfs(s, flow_inf)) {
                f += pushed;
            }
        }
        return f;
    }
};
bool vis[maxn];
vector<pair<LL, LL>> v[maxn];
int main(){
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	cout.tie(nullptr);
	cout << fixed << setprecision(20);
	LL n, m;
	cin >> n >> m;
	for(LL i = 1; i <= n; i += 1)
		for(LL j = 1; j <= n; j += 1) if(i != j) d[i][j] = 1e10;
	for(LL i = 1; i <= m; i += 1){
		LL u, v;
		cin >> u >> v;
		if(u != v) d[u][v] = d[v][u] = 1;
	}
	for(LL k = 1; k <= n; k += 1)
		for(LL i = 1; i <= n; i += 1)
			for(LL j = 1; j <= n; j += 1)
				d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
	LL s, b, k;
	cin >> s >> b >> k;
	LL ans = 0;
	for(LL i = 1; i <= s; i += 1)
		cin >> sx[i] >> a[i] >> f[i] >> p[i];
	for(LL i = 1; i <= b; i += 1)
		cin >> bx[i] >> dd[i] >> g[i];

	Dinic dinic(2 * s + 2, 0, 2 * s + 1);
	for(LL i = 1; i <= k; i += 1){
		int u, v;
		cin >> u >> v;
		dinic.add_edge(2 * u, 2 * v, 1e17);
		vis[u] = vis[v] = true;
	}
	for(LL j = 1; j <= b; j += 1)
		v[bx[j]].push_back(make_pair(dd[j], g[j]));
	for(LL j = 1; j <= n; j += 1){
		sort(v[j].begin(), v[j].end());
		for(LL i = 1; i < (LL)v[j].size(); i += 1)
			v[j][i].second = max(v[j][i].second, v[j][i - 1].second);
	}
	for(LL i = 1; i <= s; i += 1){
		LL x = -1e15;
		for(LL j = 1; j <= n; j += 1)
			if(d[sx[i]][j] <= f[i] and v[j].size()) {
				auto p = upper_bound(v[j].begin(), v[j].end(), make_pair(a[i], (LL)1e17));
				if(p == v[j].begin()) continue;
				p --;
				x = max(x, p->second);
			}
		if(vis[i]){
			dinic.add_edge(i, 2 * s + 1, p[i]);
			if(x >= 0){
				ans += x;
				dinic.add_edge(0, 2 * i, x);
			}
			else dinic.add_edge(2 * i, 2 * s + 1, -x);
			dinic.add_edge(2 * i, i, 1e17);
		}
		else ans += max(0LL, x - p[i]);
	}
	LL flow = dinic.flow();
	assert(ans >= flow);
	cout << ans - flow;
	return 0;
}

#include <bits/stdc++.h>

#define fast_cin() ios_base::sync_with_stdio(false); cin.tie(0);
#define pb push_back

using namespace std;

typedef long double ld;
typedef long long ll;
typedef long long LL;
typedef pair <int, int> pii;
typedef pair <ll, ll> pll;

struct Edge {
  int u, v;
  LL cap, flow;
  Edge() {}
  Edge(int u, int v, LL cap): u(u), v(v), cap(cap), flow(0) {}
};

struct Dinic {
  int N;
  vector<Edge> E;
  vector<vector<int>> g;
  vector<int> d, pt;

  Dinic(int N): N(N), E(0), g(N), d(N), pt(N) {}

  void AddEdge(int u, int v, LL cap) {
    if (u != v) {
      E.emplace_back(Edge(u, v, cap));
      g[u].emplace_back(E.size() - 1);
      E.emplace_back(Edge(v, u, 0));
      g[v].emplace_back(E.size() - 1);
    }
  }

  bool BFS(int S, int T) {
    queue<int> q({S});
    fill(d.begin(), d.end(), N + 1);
    d[S] = 0;
    while(!q.empty()) {
      int u = q.front(); q.pop();
      if (u == T) break;
      for (int k: g[u]) {
        Edge &e = E[k];
        if (e.flow < e.cap && d[e.v] > d[e.u] + 1) {
          d[e.v] = d[e.u] + 1;
          q.emplace(e.v);
        }
      }
    }
    return d[T] != N + 1;
  }

  LL DFS(int u, int T, LL flow = -1) {
    if (u == T || flow == 0) return flow;
    for (int &i = pt[u]; i < g[u].size(); ++i) {
      Edge &e = E[g[u][i]];
      Edge &oe = E[g[u][i]^1];
      if (d[e.v] == d[e.u] + 1) {
        LL amt = e.cap - e.flow;
        if (flow != -1 && amt > flow) amt = flow;
        if (LL pushed = DFS(e.v, T, amt)) {
          e.flow += pushed;
          oe.flow -= pushed;
          return pushed;
        }
      }
    }
    return 0;
  }

  LL MaxFlow(int S, int T) {
    LL total = 0;
    while (BFS(S, T)) {
      fill(pt.begin(), pt.end(), 0);
      while (LL flow = DFS(S, T))
        total += flow;
    }
    return total;
  }
};

struct ship_t {
	ll x, a, f, p;
};

struct base_t {
	ll x, d, g;
	bool operator<(const base_t &o) const {
		return d < o.d;
	}
};

const int N = 1e2 + 10, S = 1e5 + 10;
const ll inf = 1e12 + 42;

ship_t ship[S];
base_t base[S];
ll g[N][N];
vector<int> dep[S];
vector<pll> bases_at[N];
bool seen[S];
ll val[S];

int main()
{
	fast_cin();
	int n, m;
	cin >> n >> m;
	for (int i = 1; i <= n; ++i) {
		for (int j = i + 1; j <= n; ++j) {
			g[i][j] = g[j][i] = inf;
		}
	}
	for (int i = 0; i < m; ++i) {
		int u, v;
		cin >> u >> v;
		g[u][v] = g[v][u] = min(g[u][v], 1ll);
	}
	for (int k = 1; k <= n; ++k) {
		for (int i = 1; i <= n; ++i) {
			for (int j = 1; j <= n; ++j) {
				g[i][j] = min(g[i][j], g[i][k] + g[k][j]);
			}
		}
	}
	int s, b, k;
	cin >> s >> b >> k;
	for (int i = 1; i <= s; ++i) {
		cin >> ship[i].x >> ship[i].a >> ship[i].f >> ship[i].p;
	}
	for (int i = 1; i <= b; ++i) {
		cin >> base[i].x >> base[i].d >> base[i].g;
	}
	sort(base + 1, base + 1 + b);
	for (int i = 1; i <= b; ++i) {
		int p = base[i].x;
		if (bases_at[p].empty() or bases_at[p].back().second < base[i].g) {
			bases_at[p].pb({base[i].d, base[i].g});
		}
	}
	Dinic dinic(s + 2);
	int source = 0, sink = s + 1;
	ll ans = 0;
	for (int i = 1; i <= s; ++i) {
		for (int p = 1; p <= n; ++p) {
			if (g[ship[i].x][p] > ship[i].f) {
				continue;
			}
			auto it = upper_bound(bases_at[p].begin(), bases_at[p].end(), make_pair(ship[i].a, inf));
			if (it != bases_at[p].begin()) {
				--it;
				val[i] = max(val[i], it->second);
			}
		}
		val[i] -= ship[i].p;
		if (val[i] >= 0) {
			ans += val[i];
			dinic.AddEdge(source, i, val[i]);
		} else {
			dinic.AddEdge(i, sink, -val[i]);
		}
	}
	for (int i = 1; i <= k; ++i) {
		int u, v;
		cin >> u >> v;
		dep[u].pb(v);
	}
	for (int i = 1; i <= s; ++i) {
		if (val[i] < 0) {
			continue;
		}
		vector<int> vis = {i};
		queue<int> q;
		q.push(i);
		seen[i] = true;
		while (!q.empty()) {
			int u = q.front();
			q.pop();
			if (val[u] < 0) {
				dinic.AddEdge(i, u, inf);
			}
			for (auto &v : dep[u]) {
				if (!seen[v]) {
					seen[v] = true;
					vis.pb(v);
					q.push(v);
				}
			}
		}
		for (auto &u : vis) {
			seen[u] = false;
		}
	}
	cout << ans - dinic.MaxFlow(source, sink);
}

#include<bits/stdc++.h>
using namespace std;

#define ll long long
#define all(aaa) aaa.begin(), aaa.end()

struct E {
    int to, i;
};

const ll INF = 1e18;
const int N = 105, M = 1e5 + 5, V = 2005, Z = 3e6, S = V - 2, T = V - 1;
int best[M], pos[M], atk[M], fuel[M], dt[V], p[V];
ll cp[Z], fl[Z], d[N][N], cost[M];
int ce = 0;
vector<E> g[V];
vector<pair<int, int>> lt[N];
bool notFree[M], loser[M];

void addEdge(int a, int b, ll c) {
    cp[ce] = c;
    g[a].push_back({b, ce++});
    cp[ce] = 0;
    g[b].push_back({a, ce++});
}

bool bfs() {
    queue<int> q;
    fill(dt, dt + V, -1);
    dt[S] = 0;
    q.push(S);

    while (!q.empty()) {
        int node = q.front();
        q.pop();
        for (E e : g[node]) {
            if (cp[e.i] > fl[e.i] && dt[e.to] == -1) {
                dt[e.to] = dt[node] + 1;
                q.push(e.to);
            }
        }
    }

    return dt[T] != -1;
}

ll dfs(int node, ll flow) {
    if (node == T)
        return flow;
    for (int &i = p[node]; i < g[node].size(); i++) {
        E e = g[node][i];
        if (cp[e.i] > fl[e.i] && dt[e.to] == dt[node] + 1)  {
            int ret = dfs(e.to, min(flow, cp[e.i] - fl[e.i]));
            if (ret) {
                fl[e.i] += ret;
                fl[e.i ^ 1] -= ret;
                return ret;
            }
        }
    }
    return 0;
}

ll maxFlow() {
    ll flow = 0;
    while (bfs()) {
        memset(p, 0, sizeof(p));
        ll ret = 0;
        while (ret = dfs(S, INF)) {
            flow += ret;
        }
    }
    return flow;
}

signed main() {
#ifdef HOME
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#endif
    ios_base::sync_with_stdio(0);
    cin.tie(0);

    int n, m;
    cin >> n >> m;

    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            d[i][j] = INF;
        }
        d[i][i] = 0;
    }

    for (int i = 0; i < m; i++) {
        int a, b;
        cin >> a >> b;
        a--, b--;
        d[b][a] = d[a][b] = 1;
    }

    for (int i = 0; i < n; i++)  {
        for (int j = 0; j < n; j++) {
            for (int k = 0; k < n; k++) {
                d[j][k] = min(d[j][i] + d[i][k], d[j][k]);
            }
        }
    }

    int s, b, k;
    cin >> s >> b >> k;

    for (int i = 0; i < s; i++) {
        cin >> pos[i] >> atk[i] >> fuel[i] >> cost[i];
        pos[i]--;
    }

    for (int i = 0; i < b; i++) {
        int pl, def, gold;
        cin >> pl >> def >> gold;
        pl--;
        lt[pl].push_back({def, gold});
    }

    for (int i = 0; i < n; i++) {
        lt[i].push_back({0, 0});
        sort(all(lt[i]));
        for (int j = 1; j < lt[i].size(); j++) {
            lt[i][j].second = max(lt[i][j].second, lt[i][j - 1].second);
        }
    }

    for (int i = 0; i < s; i++) {
        loser[i] = true;
        for (int j = 0; j < n; j++) {
            if (d[pos[i]][j] <= fuel[i]) {
                int q = upper_bound(lt[j].begin(), lt[j].end(), make_pair(atk[i] + 1, -1)) - lt[j].begin();
                if (q > 0)
                    loser[i] = false;
                best[i] = max(best[i], lt[j][q - 1].second);
            }
        }
    }

    vector<int> vip;
    vector<pair<int, int>> dep;

    for (int i = 0; i < k; i++) {
        int a, b;
        cin >> a >> b;
        a--, b--;
        vip.push_back(a);
        vip.push_back(b);

        notFree[a] = notFree[b] = 1;

        dep.push_back({a, b});
    }

    sort(all(vip));
    vip.erase(unique(all(vip)), vip.end());

    ll ans = 0;

    for (int i = 0; i < s; i++) {
        if (!notFree[i] && best[i] > cost[i]) {
            ans += best[i] - cost[i];
            // cout << best[i] - cost[i] << "\n";
        }
    }

    for (int i = 0; i < vip.size(); i++) {
        if (loser[vip[i]])
            cost[vip[i]] = INF;

        addEdge(S, i, cost[vip[i]]);
        addEdge(i, T, best[vip[i]]);
        ans += best[vip[i]];
    }

    for (auto e : dep) {
        e.first = lower_bound(all(vip), e.first) - vip.begin();
        e.second = lower_bound(all(vip), e.second) - vip.begin();
        addEdge(e.second, e.first, INF);
    }

    ans -= maxFlow();

    cout << ans;

    return 0;
}

#include <iostream>
#include <algorithm>
#include <vector>
#include <map>

#define X first
#define Y second

using namespace std;

const int maxn = 2020;
const int inf = 1e9 + 7;

struct edge {
	int a, b, cap, flow;
	edge(int a, int b, int cap) : a(a), b(b), cap(cap), flow(0) {}
};

int S = 0, T, dist[maxn], q[maxn], ptr[maxn];
vector<edge> e;
vector<int> g[maxn];

void add_edge(int a, int b, int cap) {
	g[a].push_back((int)e.size());
	e.push_back(edge(a, b, cap));
	g[b].push_back((int)e.size());
	e.push_back(edge(b, a, 0));
}

bool bfs() {
	fill(dist, dist + maxn, -1);
	dist[S] = 0;
	int qh = 0, qt = 0;
	q[qt++] = S;
	while(qh < qt and dist[T] == -1) {
		int v = q[qh++];
		for(int id : g[v]) {
			if(dist[e[id].b] == -1 and e[id].flow < e[id].cap) {
				q[qt++] = e[id].b;
				dist[e[id].b] = dist[v] + 1;
			}
		}
	}
	return dist[T] != -1;
}

int dfs(int v, int flow) {
	if(flow == 0) return 0;
	if(v == T) return flow;
	for(; ptr[v] < g[v].size(); ptr[v]++) {
		int id = g[v][ptr[v]];
		if(dist[e[id].b] != dist[v] + 1) continue;
		int pushed = dfs(e[id].b, min(flow, e[id].cap - e[id].flow));
		if(pushed) {
			e[id].flow += pushed;
			e[id ^ 1].flow -= pushed;
			return pushed;
		}
	}
	return 0;
}

long long dinic() {
	long long flow = 0;
	while(bfs()) {
		fill(ptr, ptr + maxn, 0);
		while(int pushed = dfs(S, inf)) flow += pushed;
	}
	return flow;
}

int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	int n, m;
	cin >> n >> m;
	int d[n + 1][n + 1];
	for(int i = 1; i <= n; i++) {
		for(int j = 1; j <= n; j++) {
			d[i][j] = d[j][i] = inf;
		}
		d[i][i] = 0;
	}
	for(int i= 0; i < m; i++) {
		int u, v;
		cin >> u >> v;
		if(u != v) {
			d[u][v] = d[v][u] = 1;
		}
	}
	for(int k = 1; k <= n; k++) {
		for(int i = 1; i <= n; i++) {
			for(int j = 1; j <= n; j++) {
				d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
			}
		}
	}
	int s, b, k;
	cin >> s >> b >> k;
	int spos[s], attack[s], fuel[s], price[s];
	int bpos[b], defense[b], gold[b];
	for(int i = 0; i < s; i++) {
		cin >> spos[i] >> attack[i] >> fuel[i] >> price[i];
	}
	for(int i = 0; i < b; i++) {
		cin >> bpos[i] >> defense[i] >> gold[i];
	}
	bool indep[s] = {0};
	pair<int, int> dep[k];
	for(int i = 0; i < k; i++) {
		cin >> dep[i].X >> dep[i].Y;
		indep[dep[i].X - 1] = indep[dep[i].Y - 1] = true;
	}
	vector<pair<int, int> > maxpref[n + 1];
	for(int i = 1; i <= n; i++) {
		maxpref[i].push_back({0, -2 * inf});
	}
	for(int i = 0; i < b; i++) {
		maxpref[bpos[i]].push_back({defense[i], gold[i]});
	}
	for(int i = 1; i <= n; i++) {
		sort(maxpref[i].begin(), maxpref[i].end());
		for(int j = 1; j < maxpref[i].size(); j++) {
			maxpref[i][j].Y = max(maxpref[i][j].Y, maxpref[i][j - 1].Y);
		}
	}
	int maxprofit[s];
	for(int i = 0; i < s; i++) {
		int ans = -inf * 2;
		for(int j = 1; j <= n; j++) {
			if(d[spos[i]][j] <= fuel[i]) {
				int x = upper_bound(maxpref[j].begin(), maxpref[j].end(), make_pair(attack[i], 0)) - maxpref[j].begin();
				ans = max(ans, maxpref[j][x - 1].Y - price[i]);
			}
		}
		maxprofit[i] = ans;
	}
	int nxt = 1;
	int newnum[s];
	for(int i = 0; i < s; i++) {
		if(indep[i]) newnum[i] = nxt++;
	}
	T = nxt;
	for(int i = 0; i < s; i++) {
		if(indep[i]) {
			if(maxprofit[i] > 0) add_edge(S, newnum[i], maxprofit[i]);
			else if(maxprofit[i] != -inf * 2) add_edge(newnum[i], T, -maxprofit[i]);
		}
	}
	for(int i = 0; i < k; i++) {
		add_edge(newnum[dep[i].X - 1], newnum[dep[i].Y - 1], 2 * inf);
	}
	long long ans = 0;
	for(int i = 0; i < s; i++) {
		if(maxprofit[i] > 0) ans += maxprofit[i];
	}
	cout << ans - dinic() << '\n';
	return 0;
}

#include<bits/stdc++.h>

using namespace std;

#define double long double

typedef pair<int,int> ii;
typedef pair<int,long long> il;
typedef pair<long long,long long> ll;
typedef pair<ll,int> lli;
typedef pair<long long,int> li;
typedef pair<double,double> dd;
typedef pair<ii,int> iii;
typedef pair<double,int> di;
typedef pair<int,ii> iii2;
typedef pair<ii,ii> iiii;
typedef vector<int> vi;
long long mod = 1000000007LL;
long long large = 2000000000000000000LL;

struct Edge {
	int from,to;
	long long cap,flow;
};

struct Dinic {
	int n,m,s,t;
	vector<Edge> edges;
	vector<vector<int> > G;
	vector<bool> vis;
	vector<int> dis;
	vector<int> cur;
	void init(int maxn){
		edges.clear();
		G.assign(maxn+10,vector<int>(0));
		vis.assign(maxn+10,false);
		dis.assign(maxn+10,0);
		cur.assign(maxn+10,0);
		n=maxn;
	}
	void addEdge(int from,int to,long long cap){
		edges.push_back((Edge){from,to,cap,0});
		edges.push_back((Edge){to,from,0,0});
		m=edges.size();
		G[from].push_back(m-2);
		G[to].push_back(m-1);
	}
	bool BFS() {
		vis.assign(n+10,false);
		queue<int> q;
		q.push(s);
		dis[s]=0;
		vis[s]=true;
		while(!q.empty()){
			int u=q.front();
			q.pop();
			for(int i=0;i<(int)G[u].size();i++){
				Edge& e=edges[G[u][i]];
				if(!vis[e.to]&&e.cap>e.flow){
					vis[e.to]=1;
					dis[e.to]=dis[u]+1;
					q.push(e.to);
				}
			}
		}
		return vis[t];
	}
	long long DFS(int x,long long a){
		if(x==t||a==0) return a;
		long long flow=0,f;
		for(int& i=cur[x];i<(int)G[x].size();i++){
			Edge& e=edges[G[x][i]];
			if(dis[x]+1==dis[e.to]&&(f=DFS(e.to,min(a,e.cap-e.flow)))>0){
				e.flow+=f;
				edges[G[x][i]^1].flow-=f;
				flow+=f;
				a-=f;
				if(a==0) break;
			}
		}
		return flow;
	}
	long long maxflow(int s,int t){
		this->s=s;
		this->t=t;
		long long flow=0;
		while(BFS()){
			cur.assign(n+10,0);
			flow+=DFS(s,1000000000);
		}
		return flow;
	}
	void clearflow(){
		vis.assign(n+10,false);
		dis.assign(n+10,0);
		cur.assign(n+10,0);
		for(int i=0;i<(int)edges.size();i++){
			edges[i].flow=0;
		}
	}
};

int main(){

	int n,m;
	cin>>n>>m;
	vector<vector<int> > g(n,vector<int>(n,1000000000));
	for(int i=0;i<m;i++){
		int x,y;
		cin>>x>>y;
		x--;y--;
		g[x][y] = g[y][x] =1;
	}

	for(int i=0;i<n;i++) g[i][i] = 0;
	for(int k=0;k<n;k++) for(int i=0;i<n;i++) for(int j=0;j<n;j++) g[i][j] = min(g[i][j],g[i][k]+g[k][j]);

	int s,b;
	cin>>s>>b;

	int k;
	cin>>k;

	vector<int> ps(s,0),a(s,0),f(s,0),p(s,0);
	vector<int> pb(b,0),d(b,0),gold(b,0);
	for(int i=0;i<s;i++){
		cin>>ps[i]>>a[i]>>f[i]>>p[i];
		ps[i]--;
	}
	for(int i=0;i<b;i++){
		cin>>pb[i]>>d[i]>>gold[i];
		pb[i]--;
	}

	vector<vector<ii> > adj(n);
	for(int i=0;i<b;i++){
		adj[pb[i]].push_back(ii(d[i],gold[i]));
	}
	for(int i=0;i<n;i++) sort(adj[i].begin(),adj[i].end());
	for(int i=0;i<n;i++){
		for(int j=0;j<(int)adj[i].size();j++){
			if(j) adj[i][j].second = max(adj[i][j].second,adj[i][j-1].second);
		}
	}

	for(int i=0;i<s;i++){
		int ans = 0;
		for(int j=0;j<n;j++){
			if(g[ps[i]][j]>f[i]) continue;
			int pt = upper_bound(adj[j].begin(),adj[j].end(),ii(a[i],1000000010))-adj[j].begin();
			pt--;
			if(pt>=0) ans = max(ans,adj[j][pt].second);
		}
		p[i] = ans-p[i];
	}

	Dinic din;
	din.init(s+10);
	int st = s;
	int en = st+1;
	long long sum = 0;
	for(int i=0;i<s;i++){
		if(p[i]>=0){
			din.addEdge(st,i,p[i]);
			sum+=p[i];
		}else din.addEdge(i,en,-p[i]);
	}

	for(int i=0;i<k;i++){
		int x,y;
		cin>>x>>y;
		x--;y--;
		din.addEdge(x,y,large);
	}

	cout<<sum-din.maxflow(st,en)<<endl;

    return 0;
}

#include <algorithm>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>
#define debug(...) //fprintf(stderr, __VA_ARGS__)
using namespace std;
inline char nc()
{
//    return getchar();
	static char buf[100000], *l = buf, *r = buf;
	return l==r&&(r=(l=buf)+fread(buf,1,100000,stdin),l==r)?EOF:*l++;
}
template<class T> void read(T &x)
{
	x = 0; int f = 1, ch = nc();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=nc();}
	while(ch>='0'&&ch<='9'){x=x*10-'0'+ch;ch=nc();}
	x *= f;
}
typedef long long ll;
const int inf = 1e9 + 1;
const int maxn = 100 + 5;
const int maxs = 1e5 + 5;
const int maxb = 1e5 + 5;
int n, m;
int s, b, k;
int st, ed;
int val[maxn];
int dis[maxn][maxn];
int head[maxs];
vector<int> adj[maxn];
struct data
{
    int a, b, c, d, id;
    inline bool operator < (const data &other) const
    {
        return b < other.b;
    }
} A[maxs], B[maxb];
struct edge
{
    int to, nex;
    ll cap, flow;
    edge(int to=0,int nex=0,ll cap=0,ll flow=0):to(to),nex(nex),cap(cap),flow(flow){}
};
vector<edge> G;
inline void adde(int u, int v)
{
    adj[u].push_back(v);
    adj[v].push_back(u);
}
inline void addedge(int u, int v, ll c)
{
    G.push_back(edge(v, head[u], c, 0)), head[u] = G.size() - 1;
    G.push_back(edge(u, head[v], 0, 0)), head[v] = G.size() - 1;
}
namespace dinic
{
    int dis[maxs], cur[maxs];
    bool BFS()
    {
        static int q[maxs];
        int hd = 0, tl = 0;
        memset(dis, -1, sizeof(dis));
        dis[st] = 0;
        q[tl++] = st;
        while(hd < tl)
        {
            int u = q[hd++];
            for(int i = head[u]; ~i; i = G[i].nex)
            {
                int v = G[i].to;
                if(dis[v] == -1 && G[i].cap != G[i].flow)
                {
                    dis[v] = dis[u] + 1;
                    q[tl++] = v;
                }
            }
        }
        return dis[ed] != -1;
    }
    ll DFS(int u, ll flow)
    {
        if(u == ed || flow == 0) return flow;
        ll rec = flow;
        for(int &i = cur[u]; ~i; i = G[i].nex)
        {
            int v = G[i].to;
            if(dis[v] == dis[u] + 1)
            {
                ll d = DFS(v, min(flow, (ll)G[i].cap - G[i].flow));
                G[i].flow += d;
                G[i ^ 1].flow -= d;
                flow -= d;
                if(flow == 0) break;
            }
        }
        return rec - flow;
    }
    ll maxflow()
    {
        ll flow = 0;
        while(BFS())
        {
            memcpy(cur, head, sizeof(head));
            flow += DFS(st, 1e18);
        }
        return flow;
    }
}
int adde(int x)
{
    int mx = 0;
    for(int i = 1; i <= n; ++i) if(dis[ A[x].a ][i] <= A[x].c)
    {
        mx = max(mx, val[i]);
    }
    mx -= A[x].d;
    if(mx < 0)
    {
        addedge(A[x].id, ed, -mx);
        return 0;
    }
    addedge(st, A[x].id, mx);
    return mx;
}
void BFS(int st)
{
    static int q[maxn];
    int hd = 0, tl = 0;
    for(int i = 1; i <= n; ++i) dis[st][i] = inf;
    dis[st][st] = 0;
    q[tl++] = st;
    while(hd < tl)
    {
        int u = q[hd++];
        for(unsigned int i = 0; i < adj[u].size(); ++i)
        {
            int v = adj[u][i];
            if(dis[st][v] == inf)
            {
                dis[st][v] = dis[st][u] + 1;
                q[tl++] = v;
            }
        }
    }
}
void init()
{
    for(int i = 1; i <= n; ++i) BFS(i);
}
ll solve()
{
    init();
    sort(A + 1, A + s + 1);
    sort(B + 1, B + b + 1);
    ll an = 0;
    int i = 1, j = 1;
    st = 0, ed = s + 1;
    while(i <= s && j <= b)
    {
        if(B[j].b <= A[i].b)
        {
            val[ B[j].a ] = max(val[ B[j].a ], B[j].c);
            ++j;
        }
        else
        {
            an += adde(i++);
        }
    }
    while(i <= s) an += adde(i++);
    return an - dinic :: maxflow();
}
int main()
{
    read(n), read(m);
    for(int i = 1; i <= m; ++i)
    {
        int u, v; read(u), read(v);
        adde(u, v);
    }
    read(s), read(b), read(k);
    for(int i = 1; i <= s; ++i)
    {
        read(A[i].a), read(A[i].b), read(A[i].c), read(A[i].d);
        A[i].id = i;
    }
    for(int i = 1; i <= b; ++i)
    {
        read(B[i].a), read(B[i].b), read(B[i].c);
    }
    memset(head, -1, sizeof(head));
    for(int i = 1; i <= k; ++i)
    {
        int s1, s2; read(s1), read(s2);
        addedge(s1, s2, 1e18);
    }
    printf("%I64d\n", solve());
    return 0;
}

#include <iostream>
#include <vector>
#include <algorithm>
#include <tuple>
#include <queue>
using namespace std;
typedef long long ll;
typedef tuple<int, int, int> event;

const int MAXN = 100100;
const ll INFTY = 1LL<<60;
int N, M, S, B, K;
ll dist[105][105];
ll maxG[105];
int spos[MAXN], fuel[MAXN], price[MAXN];
int bpos[MAXN], gold[MAXN];
ll profit[MAXN];
vector<event> E;

struct Edge
{
    int u, v;
    ll cap, flow;
    Edge() {}
    Edge(int u, int v, ll cap): u(u), v(v), cap(cap), flow(0) {}
};

struct Dinic
{
    const static ll INFTY = 1LL<<60;
    int N;
    vector<Edge> E;
    vector<vector<int> > g;
    vector<int> d, pt;

    Dinic(int N): N(N), E(0), g(N), d(N), pt(N) {}

    void addEdge(int u, int v, ll cap)
    {
        if (u != v)
        {
            E.push_back(Edge(u, v, cap));
            g[u].push_back(E.size() - 1);
            E.push_back(Edge(v, u, 0));
            g[v].push_back(E.size() - 1);
        }
    }

    bool BFS(int S, int T)
    {
        queue<int> q;
        q.push(S);
        fill(d.begin(), d.end(), N + 1);
        d[S] = 0;

        while (!q.empty())
        {
            int u = q.front();
            q.pop();
            if (u == T)
                break;
            for (int k : g[u])
            {
                Edge &e = E[k];
                if (e.flow < e.cap && d[e.v] > d[e.u] + 1)
                {
                    d[e.v] = d[e.u] + 1;
                    q.push(e.v);
                }
            }
        }

        return d[T] != N + 1;
    }

    ll DFS(int u, int T, ll flow = INFTY)
    {
        if (u == T || flow == 0)
            return flow;

        for (int &i = pt[u]; i < g[u].size(); ++i)
        {
            Edge &e = E[g[u][i]];
            Edge &oe = E[g[u][i]^1];
            if (d[e.v] == d[e.u] + 1)
            {
                ll amt = min(flow, e.cap - e.flow);
                if (ll pushed = DFS(e.v, T, amt))
                {
                    e.flow += pushed;
                    oe.flow -= pushed;
                    return pushed;
                }
            }
        }

        return 0;
    }

    ll maxFlow(int S, int T)
    {
        ll total = 0;
        while (BFS(S, T))
        {
            fill(pt.begin(), pt.end(), 0);
            while (ll flow = DFS(S, T))
                total += flow;
        }
        return total;
    }
};

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);

    cin >> N >> M;
    for (int i = 1; i <= N; i++)
        for (int j = i + 1; j <= N; j++)
            dist[i][j] = dist[j][i] = INFTY;
    for (int i = 0, a, b; i < M; i++)
    {
        cin >> a >> b;
        dist[a][b] = dist[b][a] = 1;
    }
    for (int k = 1; k <= N; k++)
        for (int i = 1; i <= N; i++)
            for (int j = 1; j <= N; j++)
                dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);

    cin >> S >> B >> K;
    for (int i = 1, a; i <= S; i++)
    {
        cin >> spos[i] >> a >> fuel[i] >> price[i];
        E.emplace_back(a, 1, i);
    }
    for (int i = 1, d; i <= B; i++)
    {
        cin >> bpos[i] >> d >> gold[i];
        E.emplace_back(d, 0, i);
    }

    for (int i = 1; i <= S; i++)
        profit[i] = -INFTY;
    sort(E.begin(), E.end());
    for (event e : E)
    {
        int power, type, idx;
        tie(power, type, idx) = e;
        if (type == 0) //base
            maxG[bpos[idx]] = max(maxG[bpos[idx]], (ll)gold[idx]);
        else //ship
        {
            for (int i = 1; i <= N; i++)
                if (fuel[idx] >= dist[spos[idx]][i])
                    profit[idx] = max(profit[idx], maxG[i] - price[idx]);
        }
    }

    Dinic dinic(S + 2);
    ll ans = 0;
    for (int i = 1; i <= S; i++)
    {
        if (profit[i] > 0)
        {
            dinic.addEdge(0, i, profit[i]);
            ans += profit[i];
        }
        else
            dinic.addEdge(i, S + 1, -profit[i]);
    }
    for (int i = 0, a, b; i < K; i++)
    {
        cin >> a >> b;
        dinic.addEdge(a, b, INFTY);
    }
    cout << ans - dinic.maxFlow(0, S + 1) << "\n";

    return 0;
}

#include<bits/stdc++.h>
#define re register
#define inc(i,j,k) for(re int i=j;i<=k;i++)
#define dec(i,j,k) for(re int i=j;i>=k;i--)
#define ll long long
using namespace std;
const int MAXN=105;
const int MAXM=100005;
const int inf=2147483647;
inline int read(){
	int x=0,f=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while('0'<=ch&&ch<='9'){x=x*10+ch-'0',ch=getchar();}
	return f*x;
}
int n,m,s,b,dis[MAXN][MAXN],a,c,x,f,p,val,d,g,dp[MAXM],ru[MAXM],cnt=1,head[MAXM],t,S,T,dep[MAXM],tmp;
ll ans;
inline void floyd(){
	inc(k,1,n){
		inc(i,1,n){
			inc(j,1,n) dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
		}
	}
}
struct spaceship{
	int a,f,p,val,num;
	bool flag;
	spaceship(int aa,int ff,int pp,int vval,bool fflag,int nnum){a=aa,f=ff,p=pp,val=vval,flag=fflag,num=nnum;}
};
struct castal{
	int d,g;
	castal(int dd,int gg){d=dd,g=gg;}
};
vector<spaceship> ship[MAXN];
vector<castal> cas[MAXN],cass[MAXN];
bool cmp1(spaceship x,spaceship y){return x.a<y.a;}
bool cmp2(castal x,castal y){return x.d<y.d;}
struct egde{
	int to,nxt,flow;
}e[MAXM<<2];
bool use[MAXM];
inline void add(int a,int b,int c){
	e[++cnt].to=b;
	e[cnt].nxt=head[a];
	head[a]=cnt;
	e[cnt].flow=c;
}
bool bfs(){
	queue<int> q;
	inc(i,0,s+1) dep[i]=-1;
	q.push(S),dep[S]=1;
	while(q.size()){
		int u=q.front();
		q.pop();
		for(re int i=head[u];i;i=e[i].nxt){
			int v=e[i].to;
			if(dep[v]==-1&&e[i].flow){
				dep[v]=dep[u]+1;
				q.push(v);
			}
		}
	}
	return dep[T]!=-1;
}
int dfs(int u,int f){
	if(u==T) return f;
	int res=f,k=0;
	for(re int i=head[u];i;i=e[i].nxt){
		int v=e[i].to;
		if(dep[u]+1==dep[v]&&e[i].flow){
			k=dfs(v,min(f,e[i].flow));
			if(!k) dep[v]=-1;
			e[i].flow-=k;
			e[i^1].flow+=k;
			res-=k;
		}
	}
	return f-res;
}
int main(){
	n=read(),m=read();
	inc(i,1,n){
		inc(j,1,n) dis[i][j]=1000;
	}
	inc(i,1,m){
		a=read(),c=read();
		dis[c][a]=dis[a][c]=1;
	}
	floyd();
	s=read(),b=read(),t=read();
	S=0,T=s+1;
	inc(i,1,s){
		x=read(),a=read(),f=read(),p=read();
		ship[x].push_back(spaceship(a,f,p,0,0,i));
	}
	inc(i,1,b){
		x=read(),d=read(),g=read();
		cas[x].push_back(castal(d,g));
	}
	inc(i,1,n) sort(ship[i].begin(),ship[i].end(),cmp1);
	inc(i,1,n) sort(cas[i].begin(),cas[i].end(),cmp2);
	inc(i,1,n){
		for(re int j=0;j<cas[i].size();j++){
			while(j<cas[i].size()&&cass[i].size()&&cas[i][j].g<cass[i][cass[i].size()-1].g) j++;
			if(j>=cas[i].size()) break;
			cass[i].push_back(cas[i][j]);
		}
	}
	inc(i,1,n){
		inc(j,1,n){
			if(!cass[j].size()) continue;
			int l=-1;
			for(re int k=0;k<ship[i].size();k++){
				while(l+1<cass[j].size()&&cass[j][l+1].d<=ship[i][k].a) l++;
				if(l!=-1&&ship[i][k].f>=dis[i][j]) ship[i][k].flag=1,ship[i][k].val=max(ship[i][k].val,cass[j][l].g);
			}
		}
	}
	inc(i,1,n){
		for(re int j=0;j<ship[i].size();j++){
			use[ship[i][j].num]=ship[i][j].flag;
			dp[ship[i][j].num]=ship[i][j].val-ship[i][j].p;
			ans+=max((ll)0,(ll)dp[ship[i][j].num]);
		}
	}
	inc(i,1,t){
		a=read(),c=read();
		if(use[a]&&use[c])add(a,c,inf),add(c,a,0);
	}
	inc(i,1,s){
		if(use[i]){
			if(dp[i]>0) add(S,i,dp[i]),add(i,S,0);
			else if(dp[i]<0) add(i,T,-dp[i]),add(T,i,0);
		}
	}
	while(bfs()) while(tmp=dfs(S,inf)) ans-=(ll)tmp;
	printf("%I64d",ans);
}

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    ll n, m;
    cin >> n >> m;
    vector<vector<ll>> dist((size_t) n, vector<ll>((size_t) n, (ll) 1e16));
    for (ll i = 0; i < n; i++) {
        dist[i][i] = (ll) 0;
    }
    for (ll i = 0; i < m; i++) {
        ll u, v;
        cin >> u >> v;
        u--, v--;
        dist[u][v] = dist[v][u] = 0;
    }
    for (ll k = 0; k < n; k++) {
        for (ll i = 0; i < n; i++) {
            for (ll j = 0; j < n; j++) {
                dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
            }
        }
    }
    ll s, b, k;
    cin >> s >> b >> k;
    vector<tuple<ll, ll, ll, ll>> x((size_t) s);
    for (ll i = 0; i < s; i++) {
        cin >> get<0>(x[i]) >> get<1>(x[i]) >> get<2>(x[i]) >> get<3>(x[i]);
        get<0>(x[i])--;
    }
    vector<tuple<ll, ll, ll>> y((size_t) b);
    for (ll i = 0; i < b; i++) {
        cin >> get<0>(y[i]) >> get<1>(y[i]) >> get<2>(y[i]);
        get<0>(y[i])--;
    }
    vector<map<ll, ll>> bases((size_t) n);
    for (ll i = 0; i < b; i++) {
        bases[get<0>(y[i])][get<1>(y[i])] = get<2>(y[i]);
    }
    for (ll i = 0; i < n; i++) {
        for (auto j = bases[i].begin(); j != bases[i].end();) {
            if (j == bases[i].begin() || j->second > prev(j)->second) {
                j++;
            } else {
                j = bases[i].erase(j);
            }
        }
    }
    vector<ll> damages((size_t) s, (ll) -1e16);
    for (ll i = 0; i < s; i++) {
        for (ll j = 0; j < n; j++) {
            if (get<2>(x[i]) >= dist[get<0>(x[i])][j]) {
                auto it = bases[j].upper_bound(get<1>(x[i]));
                if (it != bases[j].begin()) {
                    damages[i] = max(damages[i], prev(it)->second) - get<3>(x[i]);
                }
            }
        }
    }
    vector<vector<ll>> adj((size_t) s), adj_rev((size_t) s);
    for (ll i = 0; i < k; i++) {
        ll u, v;
        cin >> u >> v;
        u--, v--;
        if (u != v) {
            adj[u].push_back(v);
            adj_rev[v].push_back(u);
        }
    }
    vector<bool> visited((size_t) s, false);
    vector<ll> order;
    function<void(ll)> visit = [&](ll u) {
        if (!visited[u]) {
            visited[u] = true;
            for (ll v : adj[u]) {
                visit(v);
            }
            order.push_back(u);
        }
    };
    vector<bool> visited_rev((size_t) s, false);
    vector<ll> component;
    function<void(ll)> visit_rev = [&](ll u) {
        if (!visited_rev[u]) {
            visited_rev[u] = true;
            for (ll v : adj_rev[u]) {
                visit_rev(v);
            }
            component.push_back(u);
        }
    };
    vector<vector<ll>> components;
    vector<ll> components_rev((size_t) s);
    vector<ll> components_values;
    for (ll u = 0; u < s; u++) {
        if (!visited[u]) {
            order.clear();
            visit(u);
        }
    }
    reverse(order.begin(), order.end());
    for (ll v : order) {
        if (!visited_rev[v]) {
            component.clear();
            visit_rev(v);
            components_values.push_back(0);
            for (ll w : component) {
                components_rev[w] = components.size();
                components_values.back() += damages[w];
            }
            components.push_back(component);
        }
    }
    vector<set<ll>> components_adj(components.size());
    vector<set<ll>> components_adj_rev(components.size());
    for (ll u = 0; u < s; u++) {
        for (ll v : adj[u]) {
            if (components_rev[u] != components_rev[v]) {
                components_adj[components_rev[u]].insert(components_rev[v]);
                components_adj_rev[components_rev[v]].insert(components_rev[u]);
            }
        }
    }
    vector<ll> components_roots;
    for (ll u = 0; u < (ll) components.size(); u++) {
        if (components_adj_rev[u].empty()) {
            components_roots.push_back(u);
        }
    }
    function<pair<ll, ll>(ll)> components_visit = [&](ll u) {
        pair<ll, ll> i{0, components_values[u]};
        if (components_values[u] > 0) {
            i.first += components_values[u];
        }
        for (ll v : components_adj[u]) {
            pair<ll, ll> j = components_visit(v);
            if (j.first > 0) {
                i.first += j.first;
            }
            i.second += j.second;
        }
        i.first = max(i.first, i.second);
        return i;
    };
    ll o = 0;
    for (ll u : components_roots) {
        o += components_visit(u).first;
    }
    cout << o << endl;
    return 0;
}

#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define ULL unsigned long long
#define mp make_pair
#define pb push_back
#define pii pair<int,int>
#define pll pair<LL,LL>
#define x first
#define y second
#define pi acos(-1)
#define sqr(x) ((x)*(x))
#define pdd pair<double,double>
#define MEMS(x) memset(x,-1,sizeof(x))
#define MEM(x) memset(x,0,sizeof(x))
#define less Less
vector<int> v[100005];
struct Dinic{
    static const int MXN = 250000;
    struct Edge{ int v,f,re; Edge(int a,int b,int c):v(a),f(b),re(c){}};
    int n,s,t,level[MXN];
    vector<Edge> E[MXN];
    void init(int _n, int _s, int _t){
        n = _n; s = _s; t = _t;
        for (int i=0; i<=n; i++) E[i].clear();
    }
    void add_edge(int u, int v, int f){
        E[u].pb(Edge(v,f,E[v].size()));
        E[v].pb(Edge(u,0,E[u].size()-1));//direct
     //   printf("%d %d %d\n",u,v,f);
    }
    bool BFS(){
        MEMS(level);
        queue<int> que;
        que.push(s);
        level[s] = 0;
        while (!que.empty()){
            int u = que.front(); que.pop();
            for (auto it : E[u]){
                if (it.f > 0 && level[it.v] == -1){
                    level[it.v] = level[u]+1;
                    que.push(it.v);
                }
            }
        }
        return level[t] != -1;
    }
    LL DFS(int u, LL nf){
        if (u == t) return nf;
        LL res = 0;
        for (auto &it : E[u]){
            if (it.f > 0 && level[it.v] == level[u]+1){
                LL tf = DFS(it.v, min(nf,(LL)it.f));
                res += tf; nf -= tf; it.f -= tf;
                E[it.v][it.re].f += tf;
                if (nf == 0) return res;
            }
        }
        if (!res) level[u] = -1;
        return res;
    }
    LL flow(LL res=0){
        while ( BFS() )
        res += DFS(s,1e18);
        return res;
    }
}flow;
int vis[100005],s;
void go(int x,int t){
    for(auto it:v[x]){
        if(vis[it]!=t){
            flow.add_edge(t,it+s,2e9);
            vis[it]=t;
            go(it,t);
        }
    }
}
int main(){
    int n,m;
    scanf("%d %d",&n,&m);
    int dis[105][105];
    for(int i = 1;i<=n;i++){
        for(int j = 1;j<=n;j++)
            dis[i][j]=1e9;
        dis[i][i]=0;
    }
    for(int i = 0;i<m;i++){
        int x,y;
        scanf("%d %d",&x,&y);
        dis[x][y]=dis[y][x]=1;
    }
    for(int i = 1;i<=n;i++){
        for(int j = 1;j<=n;j++){
            for(int k = 1;k<=n;k++){
                dis[j][k]=min(dis[j][i]+dis[i][k],dis[j][k]);
            }
        }
    }
    int B,k;
    scanf("%d %d %d",&s,&B,&k);
    int x[100005],a[100005],f[100005],p[100005];
    vector<pii> base[105];
    for(int i = 1;i<=s;i++){
        scanf("%d %d %d %d",&x[i],&a[i],&f[i],&p[i]);
    }
    for(int i = 0;i<B;i++){
        int a,b,c;
        scanf("%d %d %d",&a,&b,&c);
        base[a].pb(mp(b,c));
    }
    for(int i = 1;i<=n;i++){
    //    base[i].pb(mp(0,0));
        sort(base[i].begin(),base[i].end());
        vector<pii> tmp=base[i];
        base[i].clear();
        base[i].pb(mp(0,0));
        for(auto it:tmp){
            if(it.y>base[i].back().y){
                base[i].pb(it);
            }
        }
       // for(auto it:base[i])
       // printf("%d %d ",it.x,it.y);
       // printf("\n");
    }
    int val[100005];
    for(int i = 1;i<=s;i++){
        val[i]=-p[i];
        for(int j = 1;j<=n;j++){
            if(dis[x[i]][j]<=f[i]){
              //  printf("%d %d\n",i,j);
                val[i]=max(val[i],(lower_bound(base[j].begin(),base[j].end(),mp(a[i],1000000009))-1)->y-p[i]);
                //printf("%d\n",(lower_bound(base[i].begin(),base[i].end(),mp(a[i],1000000000))-1)->y)
            }
        }
        printf("%d\n",val[i]);
    }
    for(int i = 0;i<k;i++){
        int a,b;
        scanf("%d %d",&a,&b);
        v[b].pb(a);
    }
    flow.init(2*s+10,0,2*s+1);
    LL ans=0;
    for(int i =1;i<=s;i++){
        if(val[i]>0){
            ans+=val[i];
            flow.add_edge(i+s,2*s+1,val[i]);
        }
        else if(val[i]<0){
            flow.add_edge(0,i,-val[i]);
            go(i,i);
        }

    }
  //  printf("%lld\n",ans);
    printf("%lld\n",ans-flow.flow());
}

#include <bits/stdc++.h>
//
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 100015;
const int maxm = 1000005;
int g[105][105];
int num[maxn];
int cnt;
void floyed(int n){
    for(int k = 1; k <= n; k++){
        for(int i = 1; i <= n; i++){
            for(int j = 1; j <= n; j++){
                g[i][j] = min(g[i][j], g[i][k]+g[k][j]);
            }
        }
    }
};
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
    while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
struct Edge{
    int to,next,cap,flow;
}edge[maxm];
int tol,head[maxn];
void init()
{
    tol=2;
    memset(head,-1,sizeof(head));
}
void addedge(int u,int v,int w,int rw=0)
{
    edge[tol].to=v;edge[tol].cap=w;edge[tol].flow=0;
    edge[tol].next=head[u];head[u]=tol++;
    edge[tol].to=u;edge[tol].cap=rw;edge[tol].flow=0;
    edge[tol].next=head[v];head[v]=tol++;
}
int Q[maxn];
int dep[maxn],cur[maxn],sta[maxn];
bool bfs(int s,int t,int n)
{
    int front=0,tail=0;
    memset(dep,-1,sizeof(dep[0])*(n+1));
    dep[s]=0;
    Q[tail++]=s;
    while(front<tail){
        int u=Q[front++];
        for(int i=head[u];i!=-1;i=edge[i].next){
            int v=edge[i].to;
            if(edge[i].cap>edge[i].flow&&dep[v]==-1){
                dep[v]=dep[u]+1;
                if(v==t){
                    return true;
                }
                Q[tail++]=v;
            }
        }
    }
    return false;
}
long long dinic(int s,int t,int n)
{
    long long maxflow=0;
    while(bfs(s,t,n)){
        for(int i=0;i<n;i++){
            cur[i]=head[i];
        }
        int u=s,tail=0;
        while(cur[s]!=-1){
            if(u==t){
                int tp=INF;
                for(int i=tail-1;i>=0;i--){
                    tp=min(tp,edge[sta[i]].cap-edge[sta[i]].flow);
                }
                maxflow+=tp;
                for(int i=tail-1;i>=0;i--){
                    edge[sta[i]].flow+=tp;
                    edge[sta[i]^1].flow-=tp;
                    if(edge[sta[i]].cap-edge[sta[i]].flow==0){
                        tail=i;
                    }
                }
                u=edge[sta[tail]^1].to;
            }else if(cur[u]!=-1&&edge[cur[u]].cap>edge[cur[u]].flow&&dep[u]+1==dep[edge[cur[u]].to]){
                sta[tail++]=cur[u];
                u=edge[cur[u]].to;
            }else{
                while(u!=s&&cur[u]==-1){
                    u=edge[sta[--tail]^1].to;
                }
                cur[u]=edge[cur[u]].next;
            }
        }
    }
    return maxflow;
}
//vector<int>fuck[100005];
int fuckacm[100005];
int ps[105];
int in[maxn], out[maxn], shipos[maxn], atk[maxn], f[maxn], p[maxn], baspos[maxn], d[maxn], gold[maxn], val[maxn];
bool svis[maxn];
#define pii pair<int,int>
vector<pii> v1[105];
int main(){
    int n, m, u, v, s, b, k;
    n = read(), m = read();
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n; j++){
            if(i==j) g[i][j] = 0;
            else g[i][j] = g[j][i] = INF;
        }
    }
    for(int i = 1; i <= m; i++){
        u = read(), v = read();
        g[u][v] = g[v][u] = 1;
    }
    floyed(n);
    s = read(), b = read(), k = read();
    for(int i = 1; i <= s; i++){
        shipos[i] = read(), atk[i] = read(), f[i] = read(), p[i] = read();
    }
    for(int i = 1; i <= b; i++){
        baspos[i] = read(), d[i] = read(), gold[i] = read();
        v1[baspos[i]].emplace_back(pii(d[i], gold[i]));
    }
    for(int i = 1; i <= k; i++){
        int tmp1, tmp2;
        tmp1 = read(), tmp2 = read();
        fuckacm[tmp1] = tmp2;
        in[tmp2]++, out[tmp1]++;
    }
    for(int i = 1; i <= n; i++){
        sort(v1[i].begin(), v1[i].end()); ps[i] = 0;
        for(int j = 1; j < v1[i].size(); j++){
            v1[i][j].second = max(v1[i][j].second, v1[i][j-1].second);
        }
    }
    for(int i = 1; i <= s; i++){
        int ma = 0;
        bool flag = false;
        for(int j = 1; j <= n; j++){
            if(g[shipos[i]][j] <= f[i]){
                if(v1[j].empty()) continue;
                while(ps[j] < v1[j].size()-1 && v1[j][ps[j]+1].first <= atk[i]) ps[j]++;
                if(v1[j][ps[j]].first <= atk[i]) ma = max(ma, v1[j][ps[j]].second), flag = true;
            }
        }
        if(!flag) svis[i] = true;
        val[i] = ma-p[i];
    }
    long long ans = 0;
    for(int i = 1; i <= s; i++){
        if(in[i] == 0 && out[i] > 0 && !svis[i]){
            if(val[i] <= 0){
                svis[i] = true;
            }
        }
        if(in[i] == 0 && out[i] == 0 && val[i]>0 && !svis[i]){
            ans += val[i];
            svis[i] = true;
        }
        if(in[i] == 0 && out[i] == 0 && val[i] < 0 && !svis[i]){
            svis[i] = true;
        }
    }
    int S = 2015+1, T = S+1;
    init();
    for(int i = 1; i <= s; i++){
        if(!svis[i]){
            if(val[i] > 0){
                num[i] = ++cnt;
                addedge(S, cnt, val[i]);
                ans += val[i];
            }
            else{
                num[i] = ++cnt;
                addedge(cnt, T, -val[i]);
            }
        }
    }
    for(int i = 1; i <= s; i++){
        if(!svis[i] && val[i] > 0)
            addedge(num[i], num[fuckacm[i]], INF);
    }
    ans -= dinic(S, T, T+1);
    cout << ans;
    return 0;
}

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    ll n, m;
    cin >> n >> m;
    vector<vector<ll>> dist((size_t) n, vector<ll>((size_t) n, (ll) 1e16));
    for (ll i = 0; i < n; i++) {
        dist[i][i] = (ll) 0;
    }
    for (ll i = 0; i < m; i++) {
        ll u, v;
        cin >> u >> v;
        u--, v--;
        dist[u][v] = dist[v][u] = 0;
    }
    for (ll k = 0; k < n; k++) {
        for (ll i = 0; i < n; i++) {
            for (ll j = 0; j < n; j++) {
                dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
            }
        }
    }
    ll s, b, k;
    cin >> s >> b >> k;
    vector<tuple<ll, ll, ll, ll>> x((size_t) s);
    for (ll i = 0; i < s; i++) {
        cin >> get<0>(x[i]) >> get<1>(x[i]) >> get<2>(x[i]) >> get<3>(x[i]);
        get<0>(x[i])--;
    }
    vector<tuple<ll, ll, ll>> y((size_t) b);
    for (ll i = 0; i < b; i++) {
        cin >> get<0>(y[i]) >> get<1>(y[i]) >> get<2>(y[i]);
        get<0>(y[i])--;
    }
    vector<map<ll, ll>> bases((size_t) n);
    for (ll i = 0; i < b; i++) {
        bases[get<0>(y[i])][get<1>(y[i])] = get<2>(y[i]);
    }
    for (ll i = 0; i < n; i++) {
        for (auto j = bases[i].begin(); j != bases[i].end();) {
            if (j == bases[i].begin() || j->second > prev(j)->second) {
                j++;
            } else {
                j = bases[i].erase(j);
            }
        }
    }
    vector<ll> damages((size_t) s, (ll) -1e16);
    for (ll i = 0; i < s; i++) {
        for (ll j = 0; j < n; j++) {
            if (get<2>(x[i]) >= dist[get<0>(x[i])][j]) {
                auto it = bases[j].upper_bound(get<1>(x[i]));
                if (it != bases[j].begin()) {
                    damages[i] = max(damages[i], prev(it)->second) - get<3>(x[i]);
                }
            }
        }
    }
    vector<vector<ll>> adj((size_t) s), adj_rev((size_t) s);
    for (ll i = 0; i < k; i++) {
        ll u, v;
        cin >> u >> v;
        u--, v--;
        if (u != v) {
            adj[v].push_back(u);
            adj_rev[u].push_back(v);
        }
    }
    vector<bool> visited((size_t) s, false);
    vector<ll> order;
    function<void(ll)> visit = [&](ll u) {
        if (!visited[u]) {
            visited[u] = true;
            for (ll v : adj[u]) {
                visit(v);
            }
            order.push_back(u);
        }
    };
    vector<bool> visited_rev((size_t) s, false);
    vector<ll> component;
    function<void(ll)> visit_rev = [&](ll u) {
        if (!visited_rev[u]) {
            visited_rev[u] = true;
            for (ll v : adj_rev[u]) {
                visit_rev(v);
            }
            component.push_back(u);
        }
    };
    vector<vector<ll>> components;
    vector<ll> components_rev((size_t) s);
    vector<ll> components_values;
    for (ll u = 0; u < s; u++) {
        if (!visited[u]) {
            order.clear();
            visit(u);
        }
    }
    reverse(order.begin(), order.end());
    for (ll v : order) {
        if (!visited_rev[v]) {
            component.clear();
            visit_rev(v);
            components_values.push_back(0);
            for (ll w : component) {
                components_rev[w] = components.size();
                components_values.back() += damages[w];
            }
            components.push_back(component);
        }
    }
    vector<set<ll>> components_adj(components.size());
    vector<set<ll>> components_adj_rev(components.size());
    for (ll u = 0; u < s; u++) {
        for (ll v : adj[u]) {
            if (components_rev[u] != components_rev[v]) {
                components_adj[components_rev[u]].insert(components_rev[v]);
                components_adj_rev[components_rev[v]].insert(components_rev[u]);
            }
        }
    }
    vector<ll> components_roots;
    for (ll u = 0; u < (ll) components.size(); u++) {
        if (components_adj_rev[u].empty()) {
            components_roots.push_back(u);
        }
    }
    function<pair<ll, ll>(ll)> components_visit = [&](ll u) {
        pair<ll, ll> i{0, components_values[u]};
        if (components_values[u] > 0) {
            i.first += components_values[u];
        }
        for (ll v : components_adj[u]) {
            pair<ll, ll> j = components_visit(v);
            if (j.first > 0) {
                i.first += j.first;
            }
            i.second += j.second;
        }
        i.first = max(i.first, i.second);
        return i;
    };
    ll o = 0;
    for (ll u : components_roots) {
        o += components_visit(u).first;
    }
    cout << o << endl;
    return 0;
}

#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <utility>
#include <limits>

struct base_t {
    int64_t position, defense, gold;
    friend std::istream& operator >> (std::istream& flux, base_t& b) {
        flux >> b.position >> b.defense >> b.gold;
        return flux;
    }
    bool operator < (const base_t& b) const {
        if (this->defense != b.defense)
            return this->defense < b.defense;
        return this->gold < b.gold;
    }
};

struct ship_t {
    int64_t position, strength, fuel, price;
    friend std::istream& operator >> (std::istream& flux, ship_t& s) {
        flux >> s.position >> s.strength >> s.fuel >> s.price;
        return flux;
    }
};

struct Flow_Edge {
    int from, to;
    int64_t capacity, flow = 0LL;
    Flow_Edge (const int& from, const int& to, const int64_t& capacity): from (from), to (to), capacity (capacity) {
    }
};

constexpr int64_t Inf = 1e12 + 25;
using Ip = std::pair <int64_t, int64_t>;
using Vi = std::vector <int>;
using VVi = std::vector <Vi>;
using Vi64 = std::vector <int64_t>;
using VVi64 = std::vector <Vi64>;
using VIp = std::vector <Ip>;
using VVIp = std::vector <VIp>;
using Vf = std::vector <Flow_Edge>;
using Vs = std::vector <ship_t>;
using Vb = std::vector <base_t>;
using Qi = std::queue <int>;

struct Dinic {
    Vf Edges;
    VVi Adj;
    int n, s, t;
    Vi Level, Ptr;
    Qi Q;
    Dinic (const int& n, const int& s, const int& t): n (n), s (s), t (t) {
        Adj.resize (n), Level.resize (n), Ptr.resize (n);
    }
    void add_edge (const int& u, const int& v, const int64_t& cap) {
        Edges.emplace_back (Flow_Edge (u, v, cap));
        Adj[u].emplace_back (Edges.size () - 1);
        Edges.emplace_back (Flow_Edge (v, u, 0));
        Adj[v].emplace_back (Edges.size () - 1);
    }
    bool bfs () {
        while (!Q.empty ()) {
            int v = Q.front (); Q.pop ();
            for (const auto& id: Adj[v]) {
                if (Edges[id].capacity - Edges[id].flow < 1)
                    continue;
                if (Level[Edges[id].to] != -1)
                    continue;
                Level[Edges[id].to] = Level[v] + 1;
                Q.push (Edges[id].to);
            }
        }
        return Level[t] != -1;
    }
    int64_t dfs (const int& v, const int64_t& pushed) {
        if (!pushed)
            return 0LL;
        if (v == t)
            return pushed;
        for (int& cid = Ptr[v]; cid < (int)Adj[v].size (); ++ cid) {
            int id = Adj[v][cid], u = Edges[id].to;
            if (Level[v] + 1 != Level[u] || Edges[id].capacity - Edges[id].flow < 1)
                continue;
            int64_t transport = dfs (u, Edges[id].capacity - Edges[id].flow);
            if (!transport)
                continue;
            Edges[id].flow += transport;
            Edges[id ^ 1].flow -= transport;
            return transport;
        }
        return 0LL;
    }
    int64_t max_flow () {
        int64_t f = 0LL;
        while (true) {
            std::fill (Level.begin (), Level.end (), -1);
            Level[s] = 0;
            Q.push (s);
            if (!bfs ())
                break;
            std::fill (Ptr.begin (), Ptr.end (), 0);
            while (int64_t pushed = dfs (s, Inf))
                f += pushed;
        }
        return f;
    }
};

int n, m, u, v, s, b, k;
Vi64 Value;
VVi64 Cost;
Vs Ships;
Vb Bases;
VVIp Bases_at;

int main () {
    std::cin >> n >> m;
    Cost.assign (n + 1, Vi64 (n + 1, Inf));
    for (int i = 1; i <= m; ++ i)
        std::cin >> u >> v, Cost[u][v] = Cost[v][u] = std::min (Cost[u][v], 1LL);

    for (int k = 1; k <= n; ++ k)
        for (int i = 1; i <= n; ++ i)
            for (int j = 1; j <= n; ++ j)
                Cost[i][j] = std::min (Cost[i][j], Cost[i][k] + Cost[k][j]);

    std::cin >> s >> b >> k;
    Value.resize (s + 1), Bases_at.resize (n + 1);
    Ships.resize (s + 1), Bases.resize (b + 1);
    for (int i = 1; i <= s; ++ i)
        std::cin >> Ships[i];
    for (int i = 1; i <= b; ++ i)
        std::cin >> Bases[i];

    std::sort (Bases.begin () + 1, Bases.end ());
    for (int i = 1; i <= b; ++ i) {
        int pos = Bases[i].position;
        //if (Bases_at[pos].empty () || Bases_at[pos].back ().second < Bases[i].gold)
        Bases_at[pos].emplace_back (std::make_pair (Bases[i].defense, Bases[i].gold));
    }

    Dinic dinic (s + 2, 0, s + 1);
    int source = 0, sink = s + 1;
    int64_t ans = 0LL;
    for (int i = 1; i <= s; ++ i) {
        bool found = false;
        for (int p = 1; p <= n; ++ p) {
            if (Cost[Ships[i].position][p] > Ships[i].fuel)
                continue;
            auto it = std::upper_bound (Bases_at[p].begin (), Bases_at[p].end (), std::make_pair (Ships[i].strength, Inf));
            if (it != Bases_at[p].begin ())
                -- it, found = true, Value[i] = std::max (Value[i], it->second);
        }
        Value[i] -= Ships[i].price;
        if (!found)
            Value[i] = -Inf;
        if (Value[i] >= 0)
            ans += Value[i], dinic.add_edge (source, i, Value[i]);
        else
            dinic.add_edge (i, sink, -Value[i]);
    }

    for (int i = 1; i <= k; ++ i)
        std::cin >> u >> v,
        dinic.add_edge (u, v, Inf);

    std::cout << ans - dinic.max_flow ();

    return 0;
}

#include <bits/stdc++.h>
using namespace std;

const int maxn = 100 + 5;
const int maxs = 1e5 + 5;
vector<int> gr[maxs], rg[maxs], sg[maxs];
int x[maxs], a[maxs], f[maxs], p[maxs];
int y[maxs], d[maxs], g[maxs];
int w[maxn][maxn], mg[maxn];
int topo[maxs], scc[maxs], uf[maxs];
long long pf[maxs], sum[maxs], ans[maxs];
long long opt[maxs];
bool ok[maxs], used[maxs];
bool sok[maxs];

void build(int n, int s, int b) {
    vector<int> vs(s), vb(b);
    iota(vs.begin(), vs.end(), 0);
    iota(vb.begin(), vb.end(), 0);
    sort(vs.begin(), vs.end(), [&](int i, int j) {
        return a[i] < a[j];
    });
    sort(vb.begin(), vb.end(), [&](int i, int j) {
        return d[i] < d[j];
    });

    for (int i = 0; i < n; ++i) mg[i] = -1;

    for (int i = 0, j = 0; i < s; ++i) {
        while (j < b && d[vb[j]] <= a[vs[i]]) {
            mg[y[vb[j]]] = max(mg[y[vb[j]]], g[vb[j]]);
            ++j;
        }
        int res = -1;
        for (int k = 0; k < n; ++k) {
            if (w[x[vs[i]]][k] <= f[vs[i]])
                res = max(res, mg[k]);
        }
        if (res == -1) ok[vs[i]] = false;
        else ok[vs[i]] = true, pf[vs[i]] = res - p[vs[i]];
    }
}

void dfs(int x) {
    static int sz = 0;
    used[x] = true;
    for (int i = 0; i < (int)gr[x].size(); ++i) {
        int u = gr[x][i];
        if (!used[u]) dfs(u);
    }
    topo[sz++] = x;
}

void rdfs(int x, int s) {
    scc[x] = s;
    for (int i = 0; i < (int)rg[x].size(); ++i) {
        int u = rg[x][i];
        if (scc[u] == -1) rdfs(u, s);
    }
}

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

void merge(int x, int y) {
    uf[find(x)] = find(y);
}

vector<int> walk;

void dfs3(int x) {
    walk.push_back(x);
    used[x] = true;
    for (int i = 0; i < (int)sg[x].size(); ++i) {
        int u = sg[x][i];
        if (used[u]) continue;
        dfs3(u);
    }
}

int main() {
    int n, m; scanf("%d%d", &n, &m);
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < n; ++j)
            w[i][j] = i == j ? 0 : 1e8;
    }
    for (int i = 0; i < m; ++i) {
        int u, v; scanf("%d%d", &u, &v);
        --u, --v;
        if (u == v) continue;
        w[u][v] = w[v][u] = 1;
    }

    for (int k = 0; k < n; ++k) {
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < n; ++j)
                w[i][j] = min(w[i][j], w[i][k] + w[k][j]);
        }
    }

    int s, b, k; scanf("%d%d%d", &s, &b, &k);
    for (int i = 0; i < s; ++i) {
        scanf("%d%d%d%d", &x[i], &a[i], &f[i], &p[i]);
        --x[i];
    }
    for (int i = 0; i < b; ++i) {
        scanf("%d%d%d", &y[i], &d[i], &g[i]);
        --y[i];
    }

    build(n, s, b);

    while (k--) {
        int u, v; scanf("%d%d", &u, &v);
        --u, --v;
        gr[u].push_back(v);
        rg[v].push_back(u);
    }

    for (int i = 0; i < s; ++i) {
        if (!used[i]) dfs(i);
    }

    memset(scc, -1, sizeof(scc));
    int sz = 0;
    for (int i = s - 1; i >= 0; --i) {
        if (scc[topo[i]] == -1) {
            rdfs(topo[i], sz);
            ++sz;
        }
    }

    for (int i = 0; i < sz; ++i) {
        sok[i] = true;
        uf[i] = i;
    }

    for (int i = 0; i < s; ++i) {
        sok[scc[i]] &= ok[i];
        sum[scc[i]] += pf[i];
        for (int j = 0; j < (int)gr[i].size(); ++j) {
            int u = gr[i][j];
            if (scc[i] != scc[u]) {
                sg[scc[i]].push_back(scc[u]);
                merge(scc[i], scc[u]);
            }
        }
    }

    for (int i = 0; i < sz; ++i) {
        sort(sg[i].begin(), sg[i].end());
        sg[i].resize(unique(sg[i].begin(), sg[i].end()) - sg[i].begin());
    }

    memset(used, false, sizeof(used));
    for (int i = 0; i < sz; ++i) opt[i] = -1e18;
    for (int i = 0; i < sz; ++i) {
        walk.clear();
        dfs3(i);
        bool tok = true;
        long long su = 0;
        for (int j = 0; j < (int)walk.size(); ++j) {
            int u = walk[j];
            tok |= sok[u];
            su += sum[u];
            used[u] = false;
        }
        if (tok) opt[find(i)] = max(opt[find(i)], su);
    }

    long long ans = 0;
    for (int i = 0; i < sz; ++i) {
        if (find(i) == i)
            ans += max(0ll, opt[i]);
    }

    printf("%lld\n", ans);
    return 0;
}

#include <bits/stdc++.h>
//
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 100015;
const int maxm = 1000005;
int g[105][105];
int num[maxn];
int cnt;
void floyed(int n){
    for(int k = 1; k <= n; k++){
        for(int i = 1; i <= n; i++){
            for(int j = 1; j <= n; j++){
                g[i][j] = min(g[i][j], g[i][k]+g[k][j]);
            }
        }
    }
};
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
    while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
struct Edge{
    int to,next,cap,flow;
}edge[maxm];
int tol,head[maxn];
void init()
{
    tol=2;
    memset(head,-1,sizeof(head));
}
void addedge(int u,int v,int w,int rw=0)
{
    edge[tol].to=v;edge[tol].cap=w;edge[tol].flow=0;
    edge[tol].next=head[u];head[u]=tol++;
    edge[tol].to=u;edge[tol].cap=rw;edge[tol].flow=0;
    edge[tol].next=head[v];head[v]=tol++;
}
int Q[maxn];
int dep[maxn],cur[maxn],sta[maxn];
bool bfs(int s,int t,int n)
{
    int front=0,tail=0;
    memset(dep,-1,sizeof(dep[0])*(n+1));
    dep[s]=0;
    Q[tail++]=s;
    while(front<tail){
        int u=Q[front++];
        for(int i=head[u];i!=-1;i=edge[i].next){
            int v=edge[i].to;
            if(edge[i].cap>edge[i].flow&&dep[v]==-1){
                dep[v]=dep[u]+1;
                if(v==t){
                    return true;
                }
                Q[tail++]=v;
            }
        }
    }
    return false;
}
int dinic(int s,int t,int n)
{
    int maxflow=0;
    while(bfs(s,t,n)){
        for(int i=0;i<n;i++){
            cur[i]=head[i];
        }
        int u=s,tail=0;
        while(cur[s]!=-1){
            if(u==t){
                int tp=INF;
                for(int i=tail-1;i>=0;i--){
                    tp=min(tp,edge[sta[i]].cap-edge[sta[i]].flow);
                }
                maxflow+=tp;
                for(int i=tail-1;i>=0;i--){
                    edge[sta[i]].flow+=tp;
                    edge[sta[i]^1].flow-=tp;
                    if(edge[sta[i]].cap-edge[sta[i]].flow==0){
                        tail=i;
                    }
                }
                u=edge[sta[tail]^1].to;
            }else if(cur[u]!=-1&&edge[cur[u]].cap>edge[cur[u]].flow&&dep[u]+1==dep[edge[cur[u]].to]){
                sta[tail++]=cur[u];
                u=edge[cur[u]].to;
            }else{
                while(u!=s&&cur[u]==-1){
                    u=edge[sta[--tail]^1].to;
                }
                cur[u]=edge[cur[u]].next;
            }
        }
    }
    return maxflow;
}
//vector<int>fuck[100005];
int fuckacm[100005];
int ps[105];
int in[maxn], out[maxn], shipos[maxn], atk[maxn], f[maxn], p[maxn], baspos[maxn], d[maxn], gold[maxn], val[maxn];
bool svis[maxn];
#define pii pair<int,int>
vector<pii> v1[105];
int main(){
    int n, m, u, v, s, b, k;
    n = read(), m = read();
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n; j++){
            if(i==j) g[i][j] = 0;
            else g[i][j] = g[j][i] = INF;
        }
    }
    for(int i = 1; i <= m; i++){
        u = read(), v = read();
        g[u][v] = g[v][u] = 1;
    }
    floyed(n);
    s = read(), b = read(), k = read();
    for(int i = 1; i <= s; i++){
        shipos[i] = read(), atk[i] = read(), f[i] = read(), p[i] = read();
    }
    for(int i = 1; i <= b; i++){
        baspos[i] = read(), d[i] = read(), gold[i] = read();
        v1[baspos[i]].emplace_back(pii(d[i], gold[i]));
    }
    for(int i = 1; i <= k; i++){
        int tmp1, tmp2;
        tmp1 = read(), tmp2 = read();
        fuckacm[tmp1] = tmp2;
        in[tmp2]++, out[tmp1]++;
    }
    for(int i = 1; i <= s; i++){
        int ma = -INF;
        for(int j = 1; j <= n; j++){
            if(g[shipos[i]][j] <= f[i]){
                if(v1[j].empty()) continue;
                while(ps[j] < v1[j].size()-1 && v1[j][ps[j]+1].first <= atk[i]) ps[j]++;
                if(v1[j][ps[j]].first <= atk[i]) ma = max(ma, v1[j][ps[j]].second);
            }
        }
        val[i] = ma-p[i];
    }
    long long ans = 0;
    for(int i = 1; i <= s; i++){
        if(in[i] == 0 && out[i] > 0){
            if(val[i] <= 0){
                svis[i] = true;
            }
        }
        if(in[i] == 0 && out[i] == 0 && val[i]>0){
            ans += val[i];
            svis[i] = true;
        }
        if(in[i] == 0 && out[i] == 0 && val[i] < 0){
            svis[i] = true;
        }
    }
    int S = 2015+1, T = S+1;
    init();
    for(int i = 1; i <= s; i++){
        if(!svis[i]){
            if(val[i] > 0){
                num[i] = ++cnt;
                addedge(S, cnt, val[i]);
                ans += val[i];
            }
            else{
                num[i] = ++cnt;
                addedge(cnt, T, -val[i]);
            }
        }
    }
    for(int i = 1; i <= s; i++){
        if(!svis[i] && val[i] > 0)
            addedge(num[i], num[fuckacm[i]], INF);
    }
    ans -= dinic(S, T, T+1);
    cout << ans;
    return 0;
}

#include<bits/stdc++.h>
#define re register
#define inc(i,j,k) for(re int i=j;i<=k;i++)
#define dec(i,j,k) for(re int i=j;i>=k;i--)
#define ll long long
using namespace std;
const int MAXN=105;
const int MAXM=100005;
const int inf=2147483647;
inline int read(){
	int x=0,f=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while('0'<=ch&&ch<='9'){x=x*10+ch-'0',ch=getchar();}
	return f*x;
}
int n,m,s,b,dis[MAXN][MAXN],a,c,x,f,p,val,d,g,dp[MAXM],ru[MAXM],cnt=1,head[MAXM],t,S,T,dep[MAXM],tmp;
ll ans;
inline void floyd(){
	inc(k,1,n){
		inc(i,1,n){
			inc(j,1,n) dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
		}
	}
}
struct spaceship{
	int a,f,p,val,num;
	bool flag;
	spaceship(int aa,int ff,int pp,int vval,bool fflag,int nnum){a=aa,f=ff,p=pp,val=vval,flag=fflag,num=nnum;}
};
struct castal{
	int d,g;
	castal(int dd,int gg){d=dd,g=gg;}
};
vector<spaceship> ship[MAXN];
vector<castal> cas[MAXN],cass[MAXN];
bool cmp1(spaceship x,spaceship y){return x.a<y.a;}
bool cmp2(castal x,castal y){return x.d<y.d;}
struct egde{
	int to,nxt,flow;
}e[MAXM<<2];
bool use[MAXM];
inline void add(int a,int b,int c){
	e[++cnt].to=b;
	e[cnt].nxt=head[a];
	head[a]=cnt;
	e[cnt].flow=c;
}
bool bfs(){
	queue<int> q;
	inc(i,0,s+1) dep[i]=-1;
	q.push(S),dep[S]=1;
	while(q.size()){
		int u=q.front();
		q.pop();
		for(re int i=head[u];i;i=e[i].nxt){
			int v=e[i].to;
			if(dep[v]==-1&&e[i].flow){
				dep[v]=dep[u]+1;
				q.push(v);
			}
		}
	}
	return dep[T]!=-1;
}
ll dfs(int u,int f){
	if(u==T) return f;
	int res=f,k=0;
	for(re int i=head[u];i;i=e[i].nxt){
		int v=e[i].to;
		if(dep[u]+1==dep[v]&&e[i].flow){
			k=dfs(v,min(f,e[i].flow));
			if(!k) dep[v]=-1;
			e[i].flow-=k;
			e[i^1].flow+=k;
			res-=k;
		}
	}
	return f-res;
}
int main(){
	n=read(),m=read();
	inc(i,1,n){
		inc(j,1,n) dis[i][j]=1000;
	}
	inc(i,1,m){
		a=read(),c=read();
		dis[c][a]=dis[a][c]=1;
	}
	floyd();
	s=read(),b=read(),t=read();
	S=0,T=s+1;
	inc(i,1,s){
		x=read(),a=read(),f=read(),p=read();
		ship[x].push_back(spaceship(a,f,p,0,0,i));
	}
	inc(i,1,b){
		x=read(),d=read(),g=read();
		cas[x].push_back(castal(d,g));
	}
	inc(i,1,n) sort(ship[i].begin(),ship[i].end(),cmp1);
	inc(i,1,n) sort(cas[i].begin(),cas[i].end(),cmp2);
	inc(i,1,n){
		for(re int j=0;j<cas[i].size();j++){
			while(j<cas[i].size()&&cass[i].size()&&cas[i][j].g<cass[i][cass[i].size()-1].g) j++;
			if(j>=cas[i].size()) break;
			cass[i].push_back(cas[i][j]);
		}
	}
	inc(i,1,n){
		inc(j,1,n){
			if(!cass[j].size()) continue;
			int l=-1;
			for(re int k=0;k<ship[i].size();k++){
				while(l+1<cass[j].size()&&cass[j][l+1].d<=ship[i][k].a) l++;
				if(l!=-1&&ship[i][k].f>=dis[i][j]) ship[i][k].flag=1,ship[i][k].val=max(ship[i][k].val,cass[j][l].g);
			}
		}
	}
	inc(i,1,n){
		for(re int j=0;j<ship[i].size();j++){
			use[ship[i][j].num]=ship[i][j].flag;
			dp[ship[i][j].num]=ship[i][j].val-ship[i][j].p;
			ans+=max((ll)0,(ll)dp[ship[i][j].num]);
		}
	}
	inc(i,1,t){
		a=read(),c=read();
		add(a,c,inf),add(c,a,0);
	}
	inc(i,1,s){
		if(dp[i]>0) add(S,i,dp[i]),add(i,S,0);
		else if(dp[i]<0) add(i,T,-dp[i]),add(T,i,0);
	}
	while(bfs()) while(tmp=dfs(S,inf)) ans-=(ll)tmp;
	printf("%I64d",ans);
}

#include <bits/stdc++.h>
using namespace std;

typedef long long i64;

struct Dinic {
	struct Edge {
		i64 flow;
		int to, next;
	};
	vector<Edge> edges;
	vector<int> adia, at, dist;
	int S, D;
	void add_Edge(int from, int to, i64 cap) {
		edges.push_back( { cap, to, adia[from] });
		adia[from] = edges.size() - 1;
		edges.push_back( { 0, from, adia[to] });
		adia[to] = edges.size() - 1;
	}
	bool bfs() {
		queue<int> q;
		fill(dist.begin(), dist.end(), 1e9);
		dist[S] = 0;
		q.push(S);
		while (!q.empty()) {
			int x = q.front();
			q.pop();
			for (int i = adia[x]; i != -1; i = edges[i].next) {
				if (dist[edges[i].to] > dist[x] + 1 && edges[i].flow) {
					dist[edges[i].to] = 1 + dist[x];
					q.push(edges[i].to);
				}
			}
		}
		return dist[D] < 1e9;
	}
	i64 dfs(int nod, i64 fmax) {
		if (nod == D)
			return fmax;
		while (at[nod] != -1) {
			Edge &e = edges[at[nod]];
			i64 f;
			if (dist[e.to] == dist[nod] + 1 && e.flow
					&& (f = dfs(e.to, min(fmax, e.flow)))) {
				e.flow -= f;
				edges[at[nod] ^ 1].flow += f;
				return f;
			}
			at[nod] = edges[at[nod]].next;
		}
		return 0;
	}
	i64 GetFlow() {
		i64 f = 0;
		while (bfs()) {
			at = adia;
			while (i64 x = dfs(S, 1e18))
				f += x;
		}
		return f;
	}
	Dinic(int n = 0, int s = 0, int d = 0) {
		S = s, D = d;
		at = dist = adia = vector<int>(n + 1, -1);
	}
};

const int NMAX = 110;
int dmin[NMAX][NMAX];
struct Object { int cost, nod, power, id, fuel, atac; };
vector <Object> ships, bases;
vector <pair <int, int>> dependencies;
int n;
int best_cost[NMAX]; /// cel mai bun cost momentan pt o baza din nod

void get_cost_nave()
{
	vector <int> nv(ships.size());
	iota(nv.begin(), nv.end(), 0);

	sort(nv.begin(), nv.end(), [](int a, int b) {
			return ships[a].power < ships[b].power;
	});
	sort(bases.begin(), bases.end(), [](Object a, Object b) {
			return a.power < b.power;
	});

	int it = 0;
	for (auto i : nv) {
		while (it != bases.size() && ships[i].power >= bases[it].power) {
			best_cost[bases[it].nod] = max(best_cost[bases[it].nod], bases[it].cost);
			it++;
		}
		int best = 0;
		for (int nod = 1; nod <= n; nod++)
			if (dmin[nod][ships[i].nod] <= ships[i].fuel)
				best = max(best, best_cost[nod]);
		ships[i].atac = best;
	}
}

void read()
{
	int m, a, b;
	scanf("%d%d", &n, &m);
	fill(dmin[0], dmin[n + 1], 1e9);
	for (int i = 1; i <= n; i++)
		dmin[i][i] = 0;

	while (m--) {
		scanf("%d%d", &a, &b);
		dmin[a][b] = dmin[b][a] = 1;
	}

	for (int k = 1; k <= n; k++)
		for (int i = 1; i <= n; i++)
			for (int j = 1; j <= n; j++)
				dmin[i][j] = min(dmin[i][j], dmin[i][k] + dmin[k][j]);

	int s, k;
	scanf("%d%d%d", &s, &b, &k);
	ships.resize(s);
	bases.resize(b);
	dependencies.resize(k);

	for (auto & i : ships) {
		scanf("%d%d%d%d", &i.nod, &i.power, &i.fuel, &i.cost);
		i.fuel = min(i.fuel, 1000000);
	}
	for (auto & i : bases)
		scanf("%d%d%d", &i.nod, &i.power, &i.cost);
	for (auto & i : dependencies)
		scanf("%d%d", &i.first, &i.second);
}

int main()
{
	read();
	get_cost_nave();

	long long ans = 0;
	int cnt = 2, S = 1, D = 2;
	const i64 inf = 1e18;

	for (auto i : dependencies) {
		i.first--, i.second--;
		if (!ships[i.first].id)
			ships[i.first].id = ++cnt;
		if (!ships[i.second].id)
			ships[i.second].id = ++cnt;
	}
	Dinic flow(cnt + 1, S, D);

	for (auto i : ships) {
		if (i.id) {
			if (!i.atac)
				flow.add_Edge(i.id, D, inf);
			else {
				int castig = i.atac - i.cost;
				if (castig > 0) {
					ans += castig;
					flow.add_Edge(S, i.id, castig);
				}
				else
					flow.add_Edge(i.id, D, -castig);
			}
		}
		else
			ans += min(0, i.atac - i.cost);
	}

	ans -= flow.GetFlow();

	cout << ans << '\n';

	return 0;
}

#include <iostream>
#include <fstream>
#include <numeric>
#include <iomanip>
#include <cstring>
#include <string>
#include <algorithm>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <deque>

#define sz(a) (int)((a).size())
#define all(a) (a).begin(), (a).end()
#define pb push_back

using namespace std; using ll = long long; using vi = vector<int>; using pii = pair<int, int>; using ld = long double;

const int inf = (int)1e9 + 100;

int n, m;
int d[100][100];
int s, b, k;

struct ship {
	int x, a, f, p;
} ss[100000];

struct base {
	int x, d, g;
} bb[100000];

struct maxflow {
	struct edge {
		int to, c, f;
	};

	vector<edge> e;
	vector<vi> g;
	int N, S, T;
	vi pt, d;
	int A;

	bool bfs() {
		fill_n(d.begin(), N, inf);
		d[S] = 0;
		queue<int> q;
		q.push(S);
		while (!q.empty()) {
			int v = q.front();
			q.pop();
			for (int i : g[v]) {
				edge& ee = e[i];
				if (ee.c - ee.f >= A && d[ee.to] == inf) {
					d[ee.to] = d[v] + 1;
					q.push(ee.to);
				}
			}

		}
		return (d[T] != inf);
	}

	int dfs(int v, int cmin) {
		if (v == T) {
			return cmin;
		}
		for (; pt[v] < sz(g[v]); pt[v]++) {
			int i = g[v][pt[v]];
			edge& ee = e[i];
			if (ee.c - ee.f >= A && d[ee.to] == d[v] + 1) {
				int f = dfs(ee.to, min(cmin, ee.c - ee.f));
				if (f > 0) {
					ee.f += f;
					e[i ^ 1].f -= f;
					return f;
				}
			}
		}
		return 0;
	}

	void dinic() {
		d.resize(N);
		pt.resize(N);
		int mf = 0;
		for (A = inf; A; A >>= 1) {
			while (bfs()) {
				fill_n(pt.begin(), N, 0);
				while (dfs(S, inf));
			}
		}
	}

	void addEdge(int u, int v, int c) {
		static int i = 0;
		e.pb({ v, c, 0 });
		e.pb({ u, 0, 0 });
		g[u].pb(i);
		g[v].pb(i ^ 1);
		i += 2;
		//cout << u << ' ' << v << endl;
	}

	void zhfs(int v, vector<bool>& was) {
		was[v] = true;
		for (int i : g[v]) {
			edge& ee = e[i];
			if (ee.c - ee.f > 0 && !was[ee.to]) {
				zhfs(ee.to, was);
			}
		}
	}
};

vi g1[100000];
vector<pii> e;
bool ban[100000];
int w[100000];

void dfs(int v) {
	ban[v] = true;
	for (int to : g1[v]) if(!ban[to]) dfs(to);
}

vector<pii> pl[100];
vi pm[100];

int32_t main() {
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	//ifstream cin("in.txt");
	cin >> n >> m;
	for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) if(i != j) d[i][j] = inf;
	for (int i = 0; i < m; i++) {
		int u, v; cin >> u >> v; --u; --v; d[u][v] = d[v][u] = 1;
	}
	for (int k = 0; k < n; k++) for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
	cin >> s >> b >> k;
	for (int i = 0; i < s; i++) cin >> ss[i].x >> ss[i].a >> ss[i].f >> ss[i].p, --ss[i].x;
	for (int i = 0; i < b; i++) cin >> bb[i].x >> bb[i].d >> bb[i].g, --bb[i].x, pl[bb[i].x].pb({ bb[i].d, bb[i].g });
	for (int i = 0; i < n; i++) {
		if (pl[i].empty()) continue;
		sort(all(pl[i]));
		pm[i].resize(sz(pl[i]));
		pm[i][0] = pl[i][0].second;
		for (int j = 1; j < sz(pm[i]); j++) {
			pm[i][j] = max(pm[i][j - 1], pl[i][j].second);
		}
	}
	vi broken;
	maxflow grape;
	grape.N = s + 2;
	grape.S = grape.N - 2;
	grape.T = grape.N - 1;
	grape.g.resize(grape.N);
	vi ord(s); iota(all(ord), 0);
	sort(all(ord), [](int i, int j) { return ss[i].a < ss[j].a; });
	vi pt(n, -1);
	for (int i : ord) {
		int hi = -1;
		//for (int p = 0; p < n; p++) if (ss[i].f >= d[ss[i].x][p]) for (pii bas : pl[p]) if (ss[i].a >= bas.first) hi = max(hi, bas.second);
		// me for (int p = 0; p < n; p++) if (ss[i].f >= d[ss[i].x][p]) for (int t = 0; t < sz(pl[p]) && ss[i].a >= pl[p][t].first; t++) hi = max(hi, pm[p][t]);
 		//for (int j = 0; j < b; j++) if (ss[i].a >= bb[j].d && ss[i].f >= d[ss[i].x][bb[j].x]) hi = max(hi, bb[j].g);
		for (int p = 0; p < n; p++) if(ss[i].f >= d[ss[i].x][p]) {
			while (pt[p] + 1 < sz(pl[p]) && ss[i].a >= pl[p][pt[p] + 1].first) pt[p]++;
			if (pt[p] != -1) hi = max(hi, pm[p][pt[p]]);
		}
		if (hi == -1) broken.pb(i);
		else {
			hi -= ss[i].p;
			w[i] = hi;
			//cout << i << ' ' << w[i] << endl;
		}
	}
	for (int i = 0; i < k; i++) {
		int u, v; cin >> u >> v; --u; --v;
		g1[v].pb(u); e.pb({ u, v });
	}
	for (int u : broken) if (!ban[u]) dfs(u);
	for (int i = 0; i < n; i++) if (!ban[i]) {
		//cout << '!' << i << endl;
		int hi = w[i];
		if (hi < 0) grape.addEdge(i, grape.T, -hi);
		else if (hi > 0) grape.addEdge(grape.S, i, hi);
	}
	for (pii r : e) {
		int u = r.first, v = r.second;
		if (!ban[u] && !ban[v]) grape.addEdge(u, v, inf);
	}
	grape.dinic();
	vector<bool> was(grape.N, false);
	grape.zhfs(grape.S, was);
	ll ans = 0;
	for (int u = 0; u < s; u++) {
		if (was[u]) {
			ans += w[u];
		}
	}
	cout << ans;
}