#include <bits/stdc++.h>
using namespace std;
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/rope>
using namespace __gnu_pbds;
using namespace __gnu_cxx;
#ifndef rd
#define trace(...)
#define endl '\n'
#endif
#define pb push_back
#define fi first
#define se second
#define int long long
typedef long long ll;
typedef long double f80;
#define double long double
#define pii pair<int,int>
#define pll pair<ll,ll>
#define sz(x) ((long long)x.size())
#define fr(a,b,c) for(int a=b; a<=c; a++)
#define rep(a,b,c) for(int a=b; a<c; a++)
#define trav(a,x) for(auto &a:x)
#define all(con) con.begin(),con.end()
const ll infl=0x3f3f3f3f3f3f3f3fLL;
const int infi=0x3f3f3f3f;
//const int mod=998244353;
const int mod=1000000007;
typedef vector<int> vi;
typedef vector<ll> vl;
 
typedef tree<pii, null_type, less<pii>, rb_tree_tag, tree_order_statistics_node_update> oset;
auto clk=clock();
mt19937_64 rang(chrono::high_resolution_clock::now().time_since_epoch().count());
int rng(int lim) {
	uniform_int_distribution<int> uid(0,lim-1);
	return uid(rang);
}
int powm(int a, int b) {
	int res=1;
	while(b) {
		if(b&1)
			res=(res*a)%mod;
		a=(a*a)%mod;
		b>>=1;
	}
	return res;
}
 
long long readInt(long long l, long long r, char endd) {
	long long x=0;
	int cnt=0;
	int fi=-1;
	bool is_neg=false;
	while(true) {
		char g=getchar();
		if(g=='-') {
			assert(fi==-1);
			is_neg=true;
			continue;
		}
		if('0'<=g&&g<='9') {
			x*=10;
			x+=g-'0';
			if(cnt==0) {
				fi=g-'0';
			}
			cnt++;
			assert(fi!=0 || cnt==1);
			assert(fi!=0 || is_neg==false);
 
			assert(!(cnt>19 || ( cnt==19 && fi>1) ));
		} else if(g==endd) {
			if(is_neg) {
				x=-x;
			}
			assert(l<=x&&x<=r);
			return x;
		} else {
			assert(false);
		}
	}
}
string readString(int l, int r, char endd) {
	string ret="";
	int cnt=0;
	while(true) {
		char g=getchar();
		assert(g!=-1);
		if(g==endd) {
			break;
		}
		cnt++;
		ret+=g;
	}
	assert(l<=cnt&&cnt<=r);
	return ret;
}
long long readIntSp(long long l, long long r) {
	return readInt(l,r,' ');
}
long long readIntLn(long long l, long long r) {
	return readInt(l,r,'\n');
}
string readStringLn(int l, int r) {
	return readString(l,r,'\n');
}
string readStringSp(int l, int r) {
	return readString(l,r,' ');
}
 
int sum_n=0,sum_m=0,sum_q=0;
#define rsz(x, n) x.resize(n)
#define clr(x) x.clear()
class SCC {
public:
	int n,cnt; // cnt -> number of scc's formed
	vector<vector<int>> g,rg,sg,comp; // sg -> dag with all nodes compressed.
	vector<int> scc,order;
	vector<bool> vis;
	void reset() {
		clr(g),clr(rg),clr(sg),clr(comp),clr(scc),clr(order),clr(vis);
	}
	void init(int _n) {
		reset();
		n=_n,cnt=0;
		_n+=2;
		rsz(g, _n),rsz(rg,_n),rsz(sg,_n),rsz(comp,_n);
		scc.resize(_n,0);
		vis.resize(_n,0);
	}
	void add(int u, int v) {
		g[u].push_back(v);
		rg[v].push_back(u);
	}
	void compute() {
		fr(i, 1, n)
			if(!vis[i])
				dfs1(i);
		fill(all(vis),0);
		for(int i=n-1; i>=0; i--)
			if(!vis[order[i]])
				dfs2(order[i],++cnt);
	}
	void dfs1(int u) {
		vis[u]=1;
		for(int v : g[u])
			if(!vis[v])
				dfs1(v);
		order.pb(u);
	}
	void dfs2(int u, int c) {
		vis[u]=1;
		scc[u]=c;
		comp[c].pb(u);
		for(int v : rg[u]) {
			if(!vis[v])
				dfs2(v,c);
			if(vis[v]&&c!=scc[v])
				sg[scc[v]].pb(c);
		}
	}
};
 
struct Edge {
	int from,to,cap,flow,index;
	Edge(int from, int to, int cap, int 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, int 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)); // for bidirectional set cap.
	}
	void Enqueue(int v) {
		if(!active[v]&&excess[v]>0) {
			active[v]=true;
			Q.push(v);
		}
	}
	void Push(Edge &e) {
		int 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) {
		fr(v, 0, N - 1) {
			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;
		fr(i, 0, G[v].size() - 1)
			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]=1;
		fr(i, 0, (int)G[s].size() - 1) {
			excess[s]+=G[s][i].cap;
			Push(G[s][i]);
		}
		while(!Q.empty()) {
			int v=Q.front();
			Q.pop();
			active[v]=0;
			Discharge(v);
		}
		ll totflow=0;
		fr(i, 0, (int)G[s].size() - 1)
			totflow+=G[s][i].flow;
		return totflow;
	}
};
const int INF=infi;
struct MaxFlowLowerBound {
	PushRelabel PR;
	int N,s,t,s1,t1;
	ll total_demands;
	MaxFlowLowerBound(int N, int s, int t) :
			N(N), PR(N+2), s(s), t(t), s1(N), t1(N+1), total_demands(0) {
		PR.AddEdge(t,s,INF);
	}
	void AddEdge(int from, int to, ll lo, ll hi) {
		PR.AddEdge(s1,to,lo);
		PR.AddEdge(from,t1,lo);
		PR.AddEdge(from,to,hi-lo);
		total_demands+=lo;
	}
	ll GetMaxFlow() {
		if(PR.GetMaxFlow(s1,t1)<total_demands)
			return -1;
		PushRelabel PR1(N);
		ll initial=0;
		for(int i=0; i<N; i++) {
			for(auto e : PR.G[i]) {
				if(e.flow<0||e.cap==0)
					continue;
				if(e.to>=N)
					continue;
				if(i==t&&e.to==s) {
					initial=e.flow;
					continue;
				}
				PR1.AddEdge(i,e.to,e.cap-e.flow);
				PR1.AddEdge(e.to,i,e.flow);
			}
		}
		return initial+PR1.GetMaxFlow(s,t);
	}
};
 
const int N=30005;
int in[N],ut[N],oin[N],out[N];
pii il[N],ul[N];
pii oil[N],oul[N];
void solve() {
	int n=readIntSp(1,30000),m=readIntSp(0,30000),q=readIntLn(0,300000);
//	int n,m,q;
//	cin>>n>>m>>q;
	fr(i,1,n) {
		oil[i]={0,m};
		oul[i]={0,m};
		il[i]={0,m};
		ul[i]={0,m};
		in[i]=ut[i]=oin[i]=out[i]=0;
	}
	sum_n+=n;
	sum_m+=m;
	sum_q+=q;
	assert(sum_n<=60000&&sum_m<=60000&&sum_q<=600000);
	SCC G;
	G.init(n);
	vector<pii> edg;
	fr(i,1,m) {
		int u=readIntSp(1,n),v=readIntLn(1,n);
//		int u,v;
//		cin>>u>>v;
		assert(u!=v);
		G.add(u,v);
		edg.pb({u,v});
	}
	G.compute();
	for(auto e:edg) {
		out[e.fi]++;
		oin[e.se]++;
		ut[G.scc[e.fi]]++;
		in[G.scc[e.se]]++;
	}
	fr(i,1,n) {
		oil[i].se=oin[i];
		oul[i].se=out[i];
		il[i].se=in[i];
		ul[i].se=ut[i];
	}
	int c1=readIntSp(1,1000000000),c2=readIntLn(1,1000000000);
	bool swapped=0;
	if(c1>c2) {
		swapped=1;
		swap(c1,c2);
	}
	int src=2*n+2*G.cnt+1,sink=2*n+2*G.cnt+2;
	MaxFlowLowerBound F(2*n+2*G.cnt+5,src,sink);
	bool no=0;
	fr(i,1,q) {
		int t=readIntSp(1,4),w=readIntSp(1,n),x=readIntSp(1,2),l=readIntSp(0,m),r=readIntLn(l,m);
		if(G.scc[w]==1&&t<=2) {
			trace(t,w,x,l,r,ul[1]);
		}
		if(t<=2)
			w=G.scc[w];
		if(swapped)
			x^=3;
		if(x==2) {
			int total;
			if(t==1) {
				total=ut[w];
			} else if(t==2) {
				total=in[w];
			} else if(t==3) {
				total=out[w];
			} else {
				total=oin[w];
			}
			int nl=total-r,nr=total-l;
			l=nl;
			r=nr;
		}
		if(t==1) {
			ul[w].fi=max(ul[w].fi,l);
			ul[w].se=min(ul[w].se,r);
		} else if(t==2) {
			il[w].fi=max(il[w].fi,l);
			il[w].se=min(il[w].se,r);
		} else if(t==3) {
			oul[w].fi=max(oul[w].fi,l);
			oul[w].se=min(oul[w].se,r);
		} else {
			oil[w].fi=max(oil[w].fi,l);
			oil[w].se=min(oil[w].se,r);
		}
		if(w==1&&t==1)
			trace(ul[1],l,r);
	}
	fr(i,1,G.cnt)
		if(ul[i].fi>ul[i].se||il[i].fi>il[i].se) {
			no=1;
		}
	fr(i,1,n)
		if(oul[i].fi>oul[i].se||oil[i].fi>oil[i].se)
			no=1;
	if(no) {
		cout<<-1<<endl;
		return;
	}
	fr(i,1,G.cnt) {
		F.AddEdge(src, 2*n+i, ul[i].fi, ul[i].se);
		F.AddEdge(2*n+G.cnt+i, sink, il[i].fi, il[i].se);
	}
	fr(i,1,n) {
		F.AddEdge(2*n+G.scc[i], i, oul[i].fi, oul[i].se);
		F.AddEdge(n+i, 2*n+G.cnt+G.scc[i], oil[i].fi, oil[i].se);
	}
	for(auto i:edg)
		F.AddEdge(i.fi, n+i.se, 0, 1);
	int ans=F.GetMaxFlow();
	if(~ans)
		ans=m*c2+(c1-c2)*ans;
	cout<<ans<<endl;
}
 
signed main() {
	ios_base::sync_with_stdio(0),cin.tie(0);
	srand(chrono::high_resolution_clock::now().time_since_epoch().count());
	cout<<fixed<<setprecision(8);
	int t=readIntLn(1,100);
	fr(i,1,t)
		solve();
	assert(getchar()==EOF);
	return 0;
}
 