思路:按照長輩的名是孩子的姓這個關係建樹,建完樹以後求LCA,但是細節居多。坑點巨多TT
代碼如下:
/*
坑點:
存在孩子以女的長輩名作爲後綴,這種情況孩子跟長輩其實沒有關係,wa第三個點
兒子有可能出現在父親前面,wa最後一個點
3
scj sm
xx scjsdottir
xxx xxsson
10
xx scj xxx xx(應該yes)
*/
#include<iostream>
#include<cstdio>
#include<stack>
#include<cstring>
#include<map>
#include<queue>
#define maxn 100010
using namespace std;
map<string,int> ID;//每個名映射成一個整數
int sex[maxn];//每個人的性別
queue<int > F;//祖先節點們
map<int,vector<int> > C;//每個姓氏下的人
int pre[maxn];//每個人的父節點
int f[maxn];//並查集
int fa[maxn][30];//每個人的第2^j個祖先
int dep[maxn];//每個點的深度,根節點爲1
int n;
int lg[maxn];
void build()
{
while(!F.empty())
{
int now=F.front();F.pop();
//cout<<now<<" "<<dep[now]<<" "<<f[now]<<endl;
vector<int> &v=C[now];
for(int i=0;i<v.size();i++)
{
f[v[i]]=f[now];
dep[v[i]]=dep[now]+1;
fa[v[i]][0]=now;
//G[now].push_back(v[i]);
F.push(v[i]);
}
}
}
void init()
{
build();
for(int j=0;j<20;j++)
{
for(int i=1;i<=n;i++)
{
//cout<<i<<"走"<<j<<"->"<<fa[i][j]<<endl;
if(fa[i][j]<0) fa[i][j+1]=-1;
else fa[i][j+1]=fa[fa[i][j]][j];
}
}
}
int LCA(int u,int v)
{
if(dep[u]>dep[v]) swap(u,v);
int temp=dep[v]-dep[u];
for(int i=0;(1<<i)<=temp;i++) //使u,v在同一深度
{
if((1<<i)&temp)
v=fa[v][i];
}
if(v==u) return u;
for(int i=19;i>=0;i--) //兩個節點一起往上走
{
if(fa[u][i]!=fa[v][i])
{
u=fa[u][i];
v=fa[v][i];
//cout<<u<<" "<<v<<endl;
}
}
return fa[u][0];
}
int main(){
//freopen("data.out","w",stdout);
ios::sync_with_stdio(false);
cin>>n;
string xing,ming;
string ff[maxn];
for(int i=1;i<=n;i++)
{
cin>>ming>>xing;
int len=xing.length();
ID[ming]=i;
f[i]=i;
if(xing[len-1]=='m'){
sex[i]=1;
}else if(xing[len-1]=='f'){
sex[i]=0;
}else if(xing[len-1]=='n'){
sex[i]=1;
}else if(xing[len-1]=='r'){
sex[i]=0;
}
if(xing[len-1]=='m'||xing[len-1]=='f')
{
fa[i][0]=-1;dep[i]=1;f[i]=i;
F.push(i);//祖先
continue;
}
ff[i]=xing;
}
for(int i=1;i<=n;i++)
{
if(dep[i]==1) continue;
int len=ff[i].length();
if(ff[i][len-1]=='n')
{
ff[i].erase(len-4,4);
int v=ID[ff[i]];
if(sex[v]==1)//男父親
{
C[v].push_back(i);
}
else
{
fa[i][0]=-1;dep[i]=1;f[i]=i;
F.push(i);
}
}
else if(ff[i][len-1]=='r')
{
ff[i].erase(len-7,7);
int v=ID[ff[i]];
if(sex[v]==1)//男父親
{
C[v].push_back(i);
}
else
{
fa[i][0]=-1;dep[i]=1;f[i]=i;
F.push(i);
}
}
}
//for(int i=1;i<=n;i++)
init();int m;string x1,m1,x2,m2;
cin>>m;
while(m--)
{
cin>>m1>>x1>>m2>>x2;
if(!ID.count(m1)||!ID.count(m2))
{
cout<<"NA\n";continue;
}
int a=ID[m1];int b=ID[m2];
if(sex[a]==sex[b])
{
cout<<"Whatever\n";continue;
}
if(f[a]!=f[b])
{
cout<<"Yes\n";continue;
}
int lca=LCA(a,b);
if(dep[a]-dep[lca]<4||dep[b]-dep[lca]<4)
{
cout<<"No\n";continue;
}
else
{
cout<<"Yes\n";continue;
}
}
return 0;
}