题246.2022寒假天梯赛训练-7-5 冰岛人 (25 分)
一、题目
二、题解
这题我前面做的时候一直不带脑子地以为五代以外的要求是只要一方的五代以内的长辈没有另一方的长辈就好,然后就直接去世只对了测试点0。。。后来才发现,原来那个要求是要如果有这个公共祖先那他必须要满足在双方都是五代及以外。也就是说,为No的情况为公共祖先于双方都在五代以内或者一方有五代以内。
//五代以外包括五代必须是要满足任何一方的
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+1;
map<string,int> index0;//以人的名为key,编号为value
int parent[maxn];//表示下标对应的人的父辈
int flag[maxn];//用于存储后序寻祖对应的祖先的代数
struct People
{
string name;
string familyname;
int sex;
}P[maxn];
int main()
{
fill(parent,parent+maxn,-1);
int N;
cin>>N;
for(int i=0;i<N;i++)
{
cin>>P[i].name>>P[i].familyname;
index0[P[i].name]=i;
}
for(int i=0;i<N;i++)
{
int pos_m,pos_f;
string fa;
pos_m=P[i].familyname.find("sson");
if(pos_m!=-1)
{
fa=P[i].familyname.substr(0,pos_m);
P[i].sex=1;
}
pos_f=P[i].familyname.find("sdottir");
if(pos_f!=-1)
{
fa=P[i].familyname.substr(0,pos_f);
P[i].sex=0;
}
if(pos_m==-1&&pos_f==-1)
{
if(P[i].familyname[P[i].familyname.length()-1]=='m')
{
P[i].sex=1;
}
else
{
P[i].sex=0;
}
}
else
{
parent[i]=index0[fa];
}
}
int M;
cin>>M;
for(int i=0;i<M;i++)
{
string name1,familyname1;
string name2,familyname2;
cin>>name1>>familyname1>>name2>>familyname2;
int index1,index2;
if(index0.find(name1)==index0.end()||index0.find(name2)==index0.end())//查无此人
{
printf("NA\n");
continue;
}
else
{
index1=index0[name1];
index2=index0[name2];
}
if(P[index1].sex==P[index2].sex)//同性
{
printf("Whatever\n");
continue;
}
fill(flag,flag+maxn,0);
int cnt;
cnt=1;
while(parent[index1]!=-1)//寻index1这个人的祖并存代
{
flag[index1]=cnt;//index1记为1代,这个必须标记,因为有可能这个index1就是index2这个人的祖先
index1=parent[index1];
cnt++;
}
flag[index1]=cnt;
cnt=1;
int ans=1;
while(parent[index2]!=-1)//寻index2这个人的祖并比对两个人祖宗的代数
{
//No情况包括双方都有五代以内或者一方有五代以内
if((flag[index2]>0&&flag[index2]<5&&cnt<5)||(flag[index2]>0&&flag[index2]<5&&cnt>=5)||(flag[index2]>=5&&cnt<5))
{
ans=0;
break;
}
index2=parent[index2];
cnt++;
}
if((flag[index2]>0&&flag[index2]<5&&cnt<5)||(flag[index2]>0&&flag[index2]<5&&cnt>=5)||(flag[index2]>=5&&cnt<5))//针对index2这个人的老祖设的判断
{
ans=0;
}
if(ans)
{
printf("Yes\n");
}
else
{
printf("No\n");
}
}
}