#include <iostream>
#include <string>
#include <cstdio>
#include <map>
#include <vector>
#include <cmath>
#include<algorithm>
using namespace std;
const int maxn = 200005;
int first[maxn]; //保存该人第一次访问出现的顺序
int deep[2 * maxn]; //该点的深度
int vex[2 * maxn]; //每个顺序表示的编号
int dp[maxn][20]; //保存最近祖先的在数组中的下标,不能保存深度最小的,因为通过深度得不到该点数组下标,就不用说编号了
map<string, int> mp; //给每一个人赋值一个编号
string name[maxn]; //用编号保存名字
vector<int> vec[maxn]; //保存儿子
int cnt = 0; //编号用到
int k = 0; //数组下标
void dfs(int x, int dep) //得到数组
{
vex[++k] = x; //这里肯定访问的是新节点,因为for循环只会继续下一个未访问的节点
deep[k] = dep;
first[x] = k; //所以第一次访问肯定是这里
for (int i = 0; i < vec[x].size(); i++)
{
dfs(vec[x][i], dep + 1);
vex[++k] = x; //访问儿子之后又访问自己
deep[k] = dep;
}
}
void RMQ()
{
for (int i = 1; i <= k; i++) //dp[i][j]保存的是深度最小的那一个的下标
{
dp[i][0] = i; //下标为i的数组往后1位深度最小的就是自己
}
int a, b;
for (int i = 1; i < 20; i++) //20足够了
{
for (int j = 1; j <= k; j++)
{
if (j + (1 << i) - 1 <= k)
{
a = dp[j][i - 1];
b = dp[j + (1 << (i - 1))][i - 1];
dp[j][i] = deep[a] > deep[b] ? b : a; //得到深度最小的数组下标
}
}
}
}
void query(string name1, string name2) //询问
{
int b = max(first[mp[name1]], first[mp[name2]]); //表示第一次访问的节点数组下标较大的一个
int a = min(first[mp[name1]], first[mp[name2]]);
int k = log2(b - a + 1); //2的k次方可能不能包含b-a-1个数
int c = dp[a][k];
int d = dp[b - (1 << k) + 1][k];
int res = deep[c] > deep[d] ? d : c; //得到深度最小的那一个的下标
cout<< name[vex[res]] << endl; //通过编号得到结果
}
int solve(string s) //给每一个字符串一个不同的编号,相当于不同的人
{
if (mp.count(s) != 0)
{
return mp[s];
}
name[++cnt] = s; //通过编号保存人名
return mp[s] = cnt;
}
int main()
{
//freopen("Text.txt", "r", stdin);
int ncase;
string name1, name2;
int m, n;
int f, s;
cin >> m;
for (int i = 0; i < m; i++)
{
cin >> name1 >> name2;
f = solve(name1);
s = solve(name2);
vec[f].push_back(s); //保存儿子
}
dfs(1, 1);
/*for (int j = 1; j <= k; j++)
cout << vex[j] << " ";
cout << endl;*/
RMQ();
cin >> n;
while (n--)
{
cin >> name1 >> name2;
query(name1, name2);
}
return 0;
}