题目链接:https://pintia.cn/problem-sets/994805046380707840/problems/994805061769609216
题意:两个异性的人五服之内不得通婚,给出n个人的信息,包括id、性别、父母id(父母不可考的为-1),给出k组询问,若两个人同性,输出"Never Mind“,异性可通婚输出Yes,异性不可通婚输出No。
思路:看完题就感觉是个并查集的题,然后一直在往并查集这个方向想,可是怎么也想不到怎么处理五代之内的祖先的问题,无奈去查了下,看到别人的思路是dfs,醍醐灌顶,对啊,数据这么小,直接搜索两个人的五代之内的祖先有没有交集不就行了,唉,还是做的题目太少了,容易局限于一个角度。
好了,回归题目,这个题目有个很坑的地方,输入的询问可能会问到没有出现的id,这种情况就不会有近亲的可能,但不知道其性别,所以其性别可M可F。因为id为5位,我们1e5+5大小的结构体数组就可存所有人的信息了,结构体中包含性别,父母id,因为上面提到其性别可能出现3种情况,因此用0表示可M可F,用1表示M,用2表示F;父母id初始化为-1,输入个人信息的时候要注意要同时初始化其父母的性别,父为M,母为F。回答询问时若出现未出现的人直接输出”Yes“,若两人性别相同输出”Never Mind“(^_^),最后一种为异性情况,用dfs1搜索t1五代以内的祖先,保存在set中,用dfs2搜索t2五代以内的祖先,若有交集令flag=1,否则flag=0,然后输出相应的信息即可。
AC代码:
#include<bits/stdc++.h>
using namespace std; struct node{
int sex,fa,ma;
}a[]; int n,k,t1,t2,t3,flag;
char c;
set<int> s; void dfs1(int p,int num){
if(num>=) return;
int ff=a[p].fa,mm=a[p].ma;
if(ff>=){
s.insert(ff);
dfs1(ff,num+);
}
if(mm>=){
s.insert(mm);
dfs1(mm,num+);
}
} void dfs2(int p,int num){
if(num>=) return;
int ff=a[p].fa,mm=a[p].ma;
if(s.count(ff)||s.count(mm)){
flag=;
return;
}
if(ff>=){
dfs2(ff,num+);
if(flag) return;
}
if(mm>=){
dfs2(mm,num+);
if(flag) return;
}
} int main(){
scanf("%d",&n);
for(int i=;i<;++i)
a[i].fa=a[i].ma=-;
while(n--){
scanf("%d %c%d%d",&t1,&c,&t2,&t3);
a[t1].sex=(c=='M')?:;
a[t1].fa=t2,a[t1].ma=t3;
a[t2].sex=;
a[t3].sex=;
}
scanf("%d",&k);
while(k--){
scanf("%d%d",&t1,&t2);
if(!a[t1].sex||!a[t2].sex)
printf("Yes\n");
if(a[t1].sex==a[t2].sex)
printf("Never Mind\n");
else{
flag=;
s.clear();
dfs1(t1,);
dfs2(t2,);
if(flag)
printf("No\n");
else
printf("Yes\n");
}
}
return ;
}