import sys
from collections import defaultdict
sys.setrecursionlimit(10**7)

class SegmentTree:
    def __init__(self, data, k):
        self.n = len(data)
        self.k = k
        self.tree = [0] * (4 * self.n)
        self.build(data, 1, 0, self.n-1)

    def build(self, data, node, start, end):
        if start == end:
            self.tree[node] = data[start]
        else:
            mid = (start + end) // 2
            self.build(data, 2*node, start, mid)
            self.build(data, 2*node+1, mid+1, end)
            self.tree[node] = self.tree[2*node] & self.tree[2*node+1]

    def query(self, node, start, end, l, r):
        if r < start or end < l:
            return (1 << self.k) - 1
        if l <= start and end <= r:
            return self.tree[node]
        mid = (start + end) // 2
        left = self.query(2*node, start, mid, l, r)
        right = self.query(2*node+1, mid+1, end, l, r)
        return left & right

class HLD:
    def __init__(self, n, k, adj, color_sets):
        self.n = n
        self.k = k
        self.adj = adj
        self.color_sets = color_sets
        self.size = [0] * (n+1)
        self.depth = [0] * (n+1)
        self.parent = [0] * (n+1)
        self.heavy = [-1] * (n+1)
        self.head = [0] * (n+1)
        self.pos = [0] * (n+1)
        self.curr_pos = 0

        self.dfs(1, 0)
        self.decompose(1, 1)

        data = [0] * n
        for u in range(1, n+1):
            bitset = 0
            for c in self.color_sets[u]:
                bitset |= 1 << (c - 1)
            data[self.pos[u]] = bitset

        self.segtree = SegmentTree(data, k)

    def dfs(self, u, p):
        self.size[u] = 1
        self.parent[u] = p
        max_size = 0
        for v in self.adj[u]:
            if v == p:
                continue
            self.depth[v] = self.depth[u] + 1
            self.dfs(v, u)
            self.size[u] += self.size[v]
            if self.size[v] > max_size:
                max_size = self.size[v]
                self.heavy[u] = v

    def decompose(self, u, h):
        self.head[u] = h
        self.pos[u] = self.curr_pos
        self.curr_pos += 1
        if self.heavy[u] != -1:
            self.decompose(self.heavy[u], h)
        for v in self.adj[u]:
            if v != self.parent[u] and v != self.heavy[u]:
                self.decompose(v, v)

    def query_path(self, u, v):
        res = (1 << self.k) - 1
        while self.head[u] != self.head[v]:
            if self.depth[self.head[u]] < self.depth[self.head[v]]:
                u, v = v, u
            start = self.pos[self.head[u]]
            end = self.pos[u]
            res &= self.segtree.query(1, 0, self.n - 1, start, end)
            u = self.parent[self.head[u]]
        if self.depth[u] > self.depth[v]:
            u, v = v, u
        res &= self.segtree.query(1, 0, self.n - 1, self.pos[u], self.pos[v])
        return bin(res).count('1')

def main():
    t = int(input())
    output = []
    for _ in range(t):
        n, k, s, q = map(int, input().split())
        adj = defaultdict(list)
        for __ in range(n-1):
            u, v = map(int, input().split())
            adj[u].append(v)
            adj[v].append(u)

        color_sets = {i: set() for i in range(1, n+1)}
        for __ in range(s):
            v, x = map(int, input().split())
            color_sets[v].add(x)

        queries = []
        for __ in range(q):
            u, v = map(int, input().split())
            queries.append((u, v))

        hld = HLD(n, k, adj, color_sets)
        results = [str(hld.query_path(u, v)) for u, v in queries]
        output.append(' '.join(results))

    print('\n'.join(output))

main()
