冰島人沿用的是維京人古老的父系姓制,孩子的姓等於父親的名加後綴,如果是兒子就加 sson,女兒則加 sdottir。因爲冰島人口較少,爲避免近親繁衍,本地人交往前先用個 App 查一下兩人祖宗若干代有無聯繫。本題就請你實現這個 App 的功能。
輸入格式:
輸入首先在第一行給出一個正整數 N(1<N≤10
5
),爲當地人口數。隨後 N 行,每行給出一個人名,格式爲:名 姓(帶性別後綴),兩個字符串均由不超過 20 個小寫的英文字母組成。維京人後裔是可以通過姓的後綴判斷其性別的,其他人則是在姓的後面加 m 表示男性、f 表示女性。題目保證給出的每個維京家族的起源人都是男性。
隨後一行給出正整數 M,爲查詢數量。隨後 M 行,每行給出一對人名,格式爲:名1 姓1 名2 姓2。注意:這裏的姓是不帶後綴的。四個字符串均由不超過 20 個小寫的英文字母組成。
題目保證不存在兩個人是同名的。
輸出格式:
對每一個查詢,根據結果在一行內顯示以下信息:
若兩人爲異性,且五代以內無公共祖先,則輸出 Yes;
若兩人爲異性,但五代以內(不包括第五代)有公共祖先,則輸出 No;
若兩人爲同性,則輸出 Whatever;
若有一人不在名單內,則輸出 NA。
所謂“五代以內無公共祖先”是指兩人的公共祖先(如果存在的話)必須比任何一方的曾祖父輩分高。
輸入樣例:
15
chris smithm
adam smithm
bob adamsson
jack chrissson
bill chrissson
mike jacksson
steve billsson
tim mikesson
april mikesdottir
eric stevesson
tracy timsdottir
james ericsson
patrick jacksson
robin patricksson
will robinsson
6
tracy tim james eric
will robin tracy tim
april mike steve bill
bob adam eric steve
tracy tim tracy tim
x man april mikes
輸出樣例:
Yes
No
No
Whatever
Whatever
NA
#include<iostream>
#include<cstdio>
#include<map>
#include<algorithm>
#include<vector>
using namespace std;
struct node{
int sex;
string f;
};
map<string,node>m;
int check(string s1,string s2)
{
int fa=1,fb=1;//f=1表示自己這一代,曾祖父是f=4
for(string sa=s1;!sa.empty();sa=m[sa].f,fa++)
{
fb=1;
for(string sb=s2;!sb.empty();sb=m[sb].f,fb++)
{
if(fa>=5&&fb>=5)return 1;
if(sa==sb&&(fa<5||fb<5))
{
return 0;
}
}
}
return 1;//根本沒有公共祖先
}
int main()
{
int n,t;
string s1,s11,s2,s22;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>s1>>s2;
int len=s2.size();
if(s2[len-1]=='f')
m[s1].sex=2;
else if(s2[len-1]=='m')
m[s1].sex=1;
else if(s2[len-1]=='n')
{
m[s1].sex=1;
string temp=s2.substr(0,len-4);//截取指定index的字符串(即父親的名字)
m[s1].f=temp;
}
else if(s2[len-1]=='r')
{
m[s1].sex=2;
string temp=s2.substr(0,len-7);
m[s1].f=temp;
}
}
cin>>t;
while(t--)
{
cin>>s1>>s11>>s2>>s22;
if(m.find(s1)==m.end()||m.find(s2)==m.end())//若元素不存在則返回一個指向尾部的迭代器
{
puts("NA");
}
else if(m[s1].sex==m[s2].sex)
{
puts("Whatever");
}
else
{
if(check(s1,s2))
puts("Yes");
else puts("No");
}
}
return 0;
}