import java.io.*;
import java.util.*;

public class JB
{
	public static final int MAXDIM = 30;
	public static final int UNUSED = -(MAXDIM*MAXDIM*MAXDIM+1);

	public static dominion [] empire = new dominion[MAXDIM*MAXDIM*MAXDIM];

	public static int [] list = new int[2*MAXDIM*MAXDIM*MAXDIM];

	public static int months(int n, int m, int k, int index)
	{
		int ans = 0;
		sets s = new sets(n*m*k, empire);
		while(index >= 0) {
			for(int i = index+list[index]; i<index; i++) {
				s.insert(list[i]);
			}
			if (s.numSets() > 1)
				ans++;
			index += list[index]-1;
		}
		return ans;
	}

	public static void main(String [] args)
	{
		int n=0, m=0, k=0, l=0;
		int ncases = 0;
		BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
		String line ="";
		try {
			line = in.readLine();
		} catch (Exception e) {};
		ncases = Integer.parseInt(line);
		for(int icase = 1; icase <= ncases; icase++) {
			try {
				line = in.readLine();
			} catch (Exception e) {};
			StringTokenizer str = new StringTokenizer(line);
			n = Integer.parseInt(str.nextToken());
			m = Integer.parseInt(str.nextToken());
			k = Integer.parseInt(str.nextToken());
			l = Integer.parseInt(str.nextToken());

			int i, j;
			int id = 0;
			for(i=0; i<n*m*k; i++) {
				empire[i] = new dominion();
				empire[i].id = id;
				empire[i].inEmpire = true;
				if (id % n != 0)
					empire[i].front = id-1;
				else
					empire[i].front = -1;
				if (id % n != n-1)
					empire[i].back = id+1;
				else
					empire[i].back = -1;
				if (id % (n*m) > n-1)
					empire[i].left = id-n;
				else
					empire[i].left = -1;
				if (id % (n*m) < n*(m-1))
					empire[i].right = id+n;
				else
					empire[i].right = -1;
				if (id > n*m-1)
					empire[i].down = id-n*m;
				else
					empire[i].down = -1;
				if (id < n*m*(k-1))
					empire[i].up = id+n*m;
				else
					empire[i].up = -1;
				id++;
			}

			int index = 0;
			for(i=0; i<l; i++) {
				try {
					line = in.readLine();
				} catch (Exception e) {};
				str = new StringTokenizer(line);
				int size;
				size = Integer.parseInt(str.nextToken());
				for(j=0; j<size; j++) {
					list[index++] = Integer.parseInt(str.nextToken());
				}
				list[index++] = -size;

			}
			System.out.println(months(n,m,k,index-1));
		}
	}
}

class dominion
{
	public int id;
	public boolean inEmpire;
	public boolean visited;
	public int up, down, left, right, front, back;
};

class sets
{
	public static final int MAXDIM = 30;
	public static final int UNUSED = -(MAXDIM*MAXDIM*MAXDIM+1);

	int [] a;
	int size;
	int nSets;
	dominion [] empire;

	public sets(int s, dominion [] emp) {
		size = s;
		a = new int[size];
		for(int i=0; i<size; i++)
			a[i] = UNUSED;
		nSets = 0;
		empire = emp;
	};
	public void insert(int n) {
		a[n] = -1;
		nSets++;
		checkConnected(n);
	};
	public int numSets() {return nSets;};

	public void checkConnected(int n) {
		if (empire[n].front != -1 && a[empire[n].front] > UNUSED) {
			doUnion(n, empire[n].front);
		}
		if (empire[n].back != -1 && a[empire[n].back] > UNUSED) {
			doUnion(n, empire[n].back);
		}
		if (empire[n].right != -1 && a[empire[n].right] > UNUSED) {
			doUnion(n, empire[n].right);
		}
		if (empire[n].left != -1 && a[empire[n].left] > UNUSED) {
			doUnion(n, empire[n].left);
		}
		if (empire[n].up != -1 && a[empire[n].up] > UNUSED) {
			doUnion(n, empire[n].up);
		}
		if (empire[n].down != -1 && a[empire[n].down] > UNUSED) {
			doUnion(n, empire[n].down);
		}
	};

	public void doUnion(int n, int m)
	{
		int set = m;
		while (a[set] >= 0)
			set = a[set];
		int set2 = n;
		while (a[set2] >= 0)
			set2 = a[set2];
		if (set == set2)
			return;
		int newSet = set2;
		if (a[set] < a[set2])
			newSet = set;
		while (a[m] >= 0) {
			int temp = a[m];
			a[m] = newSet;
			m = temp;
		}
		while (a[n] >= 0) {
			int temp = a[n];
			a[n] = newSet;
			n = temp;
		}
		if (a[set] < a[set2]) {		// set bigger than set2
			a[set] += a[set2];
			a[set2] = newSet;
		}
		else {
			a[set2] += a[set];
			a[set] = newSet;
		}
		nSets--;
	};
};

