The rebels have saved enough gold to launch a full-scale attack. Now the situation is flipped, the rebels will send out the spaceships to attack the Empire bases!The galaxy can be represented as an undirected graph with $$$n$$$ planets (nodes) and $$$m$$$ wormholes (edges), each connecting two planets.A total of $$$s$$$ rebel spaceships and $$$b$$$ empire bases are located at different planets in the galaxy.Each spaceship is given a location $$$x$$$, denoting the index of the planet on which it is located, an attacking strength $$$a$$$, a certain amount of fuel $$$f$$$, and a price to operate $$$p$$$.Each base is given a location $$$x$$$, a defensive strength $$$d$$$, and a certain amount of gold $$$g$$$.A spaceship can attack a base if both of these conditions hold:   the spaceship's attacking strength is greater or equal than the defensive strength of the base  the spaceship's fuel is greater or equal to the shortest distance, computed as the number of wormholes, between the spaceship's node and the base's node The rebels are very proud fighters. So, if a spaceship cannot attack any base, no rebel pilot will accept to operate it.If a spaceship is operated, the profit generated by that spaceship is equal to the gold of the base it attacks minus the price to operate the spaceship. Note that this might be negative. A spaceship that is operated will attack the base that maximizes its profit.Darth Vader likes to appear rich at all times. Therefore, whenever a base is attacked and its gold stolen, he makes sure to immediately refill that base with gold.Therefore, for the purposes of the rebels, multiple spaceships can attack the same base, in which case each spaceship will still receive all the gold of that base.The rebels have tasked Heidi and the Doctor to decide which set of spaceships to operate in order to maximize the total profit.However, as the war has been going on for a long time, the pilots have formed unbreakable bonds, and some of them refuse to operate spaceships if their friends are not also operating spaceships.They have a list of $$$k$$$ dependencies of the form $$$s_1, s_2$$$, denoting that spaceship $$$s_1$$$ can be operated only if spaceship $$$s_2$$$ is also operated.

The first line of input contains integers $$$n$$$ and $$$m$$$ ($$$1 \leq n \leq 100$$$, $$$0 \leq m \leq 10000$$$), the number of nodes and the number of edges, respectively. The next $$$m$$$ lines contain integers $$$u$$$ and $$$v$$$ ($$$1 \leq u, v \leq n$$$) denoting an undirected edge between the two nodes. The next line contains integers $$$s$$$, $$$b$$$ and $$$k$$$ ($$$1 \leq s, b \leq 10^5$$$, $$$0 \leq k \leq 1000$$$), the number of spaceships, bases, and dependencies, respectively. The next $$$s$$$ lines contain integers $$$x, a, f, p$$$ ($$$1 \leq x \leq n$$$, $$$0 \leq a, f, p \leq 10^9$$$), denoting the location, attack, fuel, and price of the spaceship. Ships are numbered from $$$1$$$ to $$$s$$$. The next $$$b$$$ lines contain integers $$$x, d, g$$$ ($$$1 \leq x \leq n$$$, $$$0 \leq d, g \leq 10^9$$$), denoting the location, defence, and gold of the base. The next $$$k$$$ lines contain integers $$$s_1$$$ and $$$s_2$$$ ($$$1 \leq s_1, s_2 \leq s$$$), denoting a dependency of $$$s_1$$$ on $$$s_2$$$.

Print a single integer, the maximum total profit that can be achieved.

NoteThe optimal strategy is to operate spaceships 1, 2, and 4, which will attack bases 1, 1, and 2, respectively.

#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>
#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>
#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;
#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>
#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>
#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;

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>
#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>
#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;
//#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 <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 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;

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;
}

#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 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>
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;
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;

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;
}

//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 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 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;
}

#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;
}

//~ 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;
}

#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>
#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 <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>

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";
}

/*
    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 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>

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;

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>
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>
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"
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 <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;
}

#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;
}

//#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 <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;
}

//#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;
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;
}