#include <iostream>
#include <vector>
#include <cmath>

using namespace std;


class SparseTable {
  private:
	typedef pair<size_t, size_t> Pair;
	vector<vector<Pair> > table;

  public:
	void Setup (const vector<size_t> &sequence) {
		const size_t length = sequence.size();
		const size_t height = static_cast<size_t>(log2(sequence.size())) + 1;
		table.resize(height);

		for (size_t i = 0; i < length; i ++) {
			table[0].push_back(make_pair(sequence[i], i));
		}

		for (size_t i = 1; i < height; i ++) {
			const size_t currentLength = length - pow(2, i) + 1;
			table[i].resize(currentLength);

			for (size_t j = 0; j < currentLength; j ++) {
				table[i][j] = min<Pair>(table[i - 1][j], table[i - 1][j + pow(2, i - 1)]);
							}
		}
	}

	Pair RangeMinimumQuery (const size_t left, const size_t right) {
		const size_t length = right - left + 1;
		const size_t power = static_cast<size_t>(log2(length));
		const size_t flooredLength = pow(2, power);

		const Pair leftValue = table[power][left];
		const size_t padding = length - flooredLength;
		const Pair rightValue = table[power][left + padding];

		return min<Pair>(leftValue, rightValue);
	}
};

class Tree {
	private:
		vector<vector<size_t> > children;
		vector<size_t> depthList;
		vector<size_t> verticesList;
		vector<size_t> indexes;
		SparseTable sparseTable;
		bool locked;

		void DFS (const size_t &vertex = 0, const size_t &depth = 0) {
			depthList.push_back(depth);
			verticesList.push_back(vertex);
			indexes[vertex] = verticesList.size() - 1;

			for (const size_t &child: children[vertex]) {
				DFS(child, depth + 1);
				depthList.push_back(depth);
				verticesList.push_back(vertex);
				indexes[vertex] = verticesList.size() - 1;
			}
		}

	public:
		Tree (const size_t &verticesCount) {
			children.resize(verticesCount);
			depthList.resize(0);
			verticesList.resize(0);
			indexes.resize(verticesCount);
			locked = false;
		}

		void addEdge (const size_t &parent, const size_t &child) {
			if (locked)
				return;

			children[parent].push_back(child);
		}

		void lockTreeAndStartProcessingQueries () {
			if (locked)
				return;

			locked = true;
			DFS();
			sparseTable.Setup(depthList);
		}

		size_t leastCommonAncestor (const size_t &firstVertex, const size_t &secondVertex) {
			if (!locked)
				return -1;

			const size_t firstIndex = indexes[firstVertex];
			const size_t secondIndex = indexes[secondVertex];
			const size_t minIndex = min<size_t>(firstIndex, secondIndex);
			const size_t maxIndex = max<size_t>(firstIndex, secondIndex);
			const size_t index = sparseTable.RangeMinimumQuery(minIndex, maxIndex).second;
			const size_t vertex = verticesList[index];
			return vertex;
		}
};



int main () {
	size_t verticesCount;
	cin >> verticesCount;

	// Build tree:
	Tree tree(verticesCount);

	for (size_t parent = 0; parent < verticesCount; parent ++) {
		size_t count;
		cin >> count;

		for (size_t j = 0; j < count; j ++) {
			size_t child;
			cin >> child;
			tree.addEdge(parent, child);
		}
	}

	// Process queries:
	size_t queriesCount;
	cin >> queriesCount;

	tree.lockTreeAndStartProcessingQueries();

	// Processing queries:
	for (size_t i = 0; i < queriesCount; i ++) {
		size_t firstVertex, secondVertex;
		cin >> firstVertex >> secondVertex;
		cout << tree.leastCommonAncestor(firstVertex, secondVertex) << endl;
	}

	return 0;
}



Measured memory_bytes: 67840