#include <bits/stdc++.h>
#define int long long
#define fi first
#define se second
using namespace std;
using ii = pair<int,int>;
const int N = 1e5+5;
int n, m, q, u, v, c, gold, silver, sum, cnt, timer = 0;
int sz[N], depth[N], par[N], tin[N], heavy[N], chain[N], L[N], R[N], ans[N];
ii edge[N];
bool ok = 1;
vector <int> adj[N], queries[N];
struct canh{
int c, u, v;
bool operator < (const canh &y){
return c < y.c;
}
} edges[N];
struct Queries{
int u, v, gold, silver;
} qr[N];
void DFS(int u,int p){
sz[u] = 1;
depth[u] = depth[p] + 1;
par[u] = p;
for (int it : adj[u]){
if (it == p) continue;
DFS(it,u);
if (sz[it] > sz[heavy[u]]) heavy[u] = it;
sz[u] += sz[it];
}
}
void HLD(int u,int p){
tin[u] = ++timer;
if (!heavy[u]) return;
chain[heavy[u]] = chain[u];
HLD(heavy[u],u);
for (int it : adj[u]){
if (it == p || it == heavy[u]) continue;
chain[it] = it;
HLD(it,u);
}
}
struct BIT{
vector <int> bit;
int n;
BIT (int _n = 0) : n(_n){
bit.assign(n + 5,0);
}
void upd(int id,int val){
while (id <= n){
bit[id] += val;
id += id & -id;
}
}
void update(int l,int r,int val){
if (l > r) return;
upd(r,val);
}
int get(int id){
int res = 0;
while (id > 0){
res += bit[id];
id -= id & -id;
}
return res;
}
int query(int l,int r){
if (l > r) return 0;
return get(r) - get(l - 1);
}
void reset(){
for (int i = 1; i <= n; i++) bit[i] = 0;
}
};
struct hld{
BIT tree;
int n;
hld (int _n = 0) : n(_n), tree(BIT(_n)) {}
int Get(int u,int v){
int res = 0;
while (chain[u] != chain[v]){
if (depth[chain[u]] < depth[chain[v]]) swap(u,v);
res += tree.query(tin[chain[u]],tin[u]);
u = par[chain[u]];
}
if (depth[u] > depth[v]) swap(u,v);
res += tree.query(tin[u] + 1,tin[v]);
return res;
}
void up(int u,int v,int val){
if (depth[u] > depth[v]) swap(u,v);
tree.update(tin[u] + 1,tin[v],val);
}
void reset(){
tree.reset();
}
};
signed main(){
ios_base::sync_with_stdio(false);
cin.tie(NULL); cout.tie(NULL);
cin >> n >> m >> q;
for (int i = 1; i < n; i++){
cin >> u >> v;
adj[u].push_back(v);
adj[v].push_back(u);
edge[i] = {u,v};
}
for (int i = 1; i <= m; i++){
cin >> u >> c;
edges[i] = {c,edge[u].fi,edge[u].se};
}
sort(edges+1,edges+1+m);
for (int i = 1; i <= q; i++){
cin >> qr[i].u >> qr[i].v >> qr[i].gold >> qr[i].silver;
L[i] = 0;
R[i] = m;
ans[i] = -1;
}
chain[1] = 1;
DFS(1,0);
HLD(1,0);
hld Sum(n);
hld Cnt(n);
while (ok){
ok = 0;
for (int i = 1; i <= q; i++){
if (L[i] > R[i]) continue;
ok = 1;
queries[(L[i] + R[i]) >> 1].push_back(i);
}
for (int i = 1; i <= m; i++){
Cnt.up(edges[i].u,edges[i].v,1);
}
for (int i = 0; i <= m; i++){
if (i){
Sum.up(edges[i].u,edges[i].v,edges[i].c);
Cnt.up(edges[i].u,edges[i].v,-1);
}
for (int it : queries[i]){
u = qr[it].u;
v = qr[it].v;
gold = qr[it].gold;
silver = qr[it].silver;
sum = Sum.Get(u,v);
cnt = Cnt.Get(u,v);
if (sum <= silver){
ans[it] = max(ans[it],gold - cnt);
L[it] = i + 1;
} else R[it] = i - 1;
}
queries[i].clear();
}
Sum.reset();
Cnt.reset();
}
for (int i = 1; i <= q; i++){
cout << ans[i] << '\n';
}
return 0;
}