#include <iostream.h>
//using namespace std;

const int MAXDIM = 30;

const int UNUSED = -(MAXDIM*MAXDIM*MAXDIM+1);

struct dominion {
	int id;
	bool inEmpire;
	bool visited;
	int up, down, left, right, front, back;
} empire[MAXDIM*MAXDIM*MAXDIM];

int list[2*MAXDIM*MAXDIM*MAXDIM];

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

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

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

	void print()
	{
		for(int i=0; i<size; i++) {
			cout << '[' << i << ':' << a[i] << ']';
		}
	};

	int *a;
	int size;
	int nSets;
};

int months(int n, int m, int k, int index)
{
	int ans = 0;
	sets s(n*m*k);
	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;
}

int main()
{
	int n, m, k, l;
	int ncases;
	cin >> ncases;
	for(int icase = 1; icase <= ncases; icase++) {
		cin >> n >> m >> k >> l;

		int i, j;
		int id = 0;
		for(i=0; i<n*m*k; i++) {
			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++) {
			int size;
			cin >> size;
			for(j=0; j<size; j++) {
				cin >> list[index++];
			}
			list[index++] = -size;

		}
		cout << months(n,m,k,index-1) << endl;
	}
	return 0;
}

