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