pta l2-16(愿天下有情人都是失散多年的兄妹)
题目链接: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代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 4 struct node{ 5 int sex,fa,ma; 6 }a[100005]; 7 8 int n,k,t1,t2,t3,flag; 9 char c; 10 set<int> s; 11 12 void dfs1(int p,int num){ 13 if(num>=5) return; 14 int ff=a[p].fa,mm=a[p].ma; 15 if(ff>=0){ 16 s.insert(ff); 17 dfs1(ff,num+1); 18 } 19 if(mm>=0){ 20 s.insert(mm); 21 dfs1(mm,num+1); 22 } 23 } 24 25 void dfs2(int p,int num){ 26 if(num>=5) return; 27 int ff=a[p].fa,mm=a[p].ma; 28 if(s.count(ff)||s.count(mm)){ 29 flag=1; 30 return; 31 } 32 if(ff>=0){ 33 dfs2(ff,num+1); 34 if(flag) return; 35 } 36 if(mm>=0){ 37 dfs2(mm,num+1); 38 if(flag) return; 39 } 40 } 41 42 int main(){ 43 scanf("%d",&n); 44 for(int i=0;i<100000;++i) 45 a[i].fa=a[i].ma=-1; 46 while(n--){ 47 scanf("%d %c%d%d",&t1,&c,&t2,&t3); 48 a[t1].sex=(c=='M')?1:2; 49 a[t1].fa=t2,a[t1].ma=t3; 50 a[t2].sex=1; 51 a[t3].sex=2; 52 } 53 scanf("%d",&k); 54 while(k--){ 55 scanf("%d%d",&t1,&t2); 56 if(!a[t1].sex||!a[t2].sex) 57 printf("Yes\n"); 58 if(a[t1].sex==a[t2].sex) 59 printf("Never Mind\n"); 60 else{ 61 flag=0; 62 s.clear(); 63 dfs1(t1,1); 64 dfs2(t2,1); 65 if(flag) 66 printf("No\n"); 67 else 68 printf("Yes\n"); 69 } 70 } 71 return 0; 72 }
朋友们,无论这个世界变得怎样,只要能够为了当时纯粹的梦想和感动坚持努力下去,不管其它人怎么样,我们也能够保持自己的本色走下去。