2018年世界杯,冰岛队因1:1平了强大的阿根廷队而一战成名。好事者发现冰岛人的名字后面似乎都有个“松”(son),于是有网友科普如下: 冰岛人沿用的是维京人古老的父系姓制,孩子的姓等于父亲的名加后缀,如果是儿子就加 sson,女儿则加 sdottir。因为冰岛人口较少,为避免近亲繁衍,本地人交往前先用个 App 查一下两人祖宗若干代有无联系。本题就请你实现这个 App 的功能。 输入格式:输入首先在第一行给出一个正整数 N(1<N≤105),为当地人口数。随后 N 行,每行给出一个人名,格式为: 随后一行给出正整数 M,为查询数量。随后 M 行,每行给出一对人名,格式为: 题目保证不存在两个人是同名的。 输出格式:对每一个查询,根据结果在一行内显示以下信息:
所谓“五代以内无公共祖先”是指两人的公共祖先(如果存在的话)必须比任何一方的曾祖父辈分高。
|
输入样例:
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
坑点说明
“五代以内无公共祖先”,哪怕C是A的祖宗18代,但C只是B的3代,A与B依旧不能结婚
C/C++
#include<bits/stdc++.h>
using namespace std;
map<string,bool> sex,apr; // firstname -> sex and appear
map<string,string> lastname;
int OP(string xName,string yName);
int main()
{
string a,b,c,d;
int N;
cin >> N;
for(int z=1;z<=N;z++){
cin >> a >> b;
apr[a] = true;
sex[a] = (b.back()=='n' || b.back()=='m');
int key = b.back()=='m' || b.back()=='f' ? 1 : b.back() == 'n' ? 4 : 7;
if(key>1){
while (key--) b.pop_back();
lastname[a] = b;
}
}
cin >> N;
while (N--){
cin >> a >> b >> c >> d;
switch (OP(a,c)) {
case 0: puts("NA"); break;
case 1: puts("Whatever");break;
case 2: puts("Yes");break;
default: puts("No");break;
}
}
return 0;
}
int OP(string xName,string yName)
{
// 有人不在名单
if(!apr[xName] || !apr[yName]) return 0;
// 两人为同性
if(sex[xName] == sex[yName]) return 1;
map<string,int> family;
for(int z=1;!xName.empty();z++){
family[xName] = z;
xName = lastname[xName];
}
for(int z=1;!yName.empty();z++){
int key = family[yName];
if(key!=0){
if(key<5 || z<5) return 233;
}
yName = lastname[yName];
}
return 2;
}