L2-2 Icelanders (25 points)
In the 2018 World Cup, Iceland became famous for its 1-1 draw with Argentina. Good people found that Icelanders seem to have a "son" behind their names, so some netizens popularized science as follows:
Input example:
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
Output example:
Yes No No Whatever Whatever NA
thinking
1. From the title, everyone's "name" is different. All of them can use "name" as identifier and map to number everyone according to the input order.
2. Remove the suffix after the Viking surname (the surname without the suffix is the name of the father)
3. At this time, we will know the number of each person's first name. Then, according to the last name of each person, we can know the number of their father's first name. (you can also use and search the set here, because each person has at most one elder, and I'm directly looping through each elder.)
4. Loop through the parents of the person to be tested, and judge whether they are the same. If they are the same, they are within five generations. (note here that in the same way, they must be higher than the great grandparents of either side. In other words, for example, if the common ancestor is the father of A and the ancestor of more than ten generations of B, it is still not possible, because it is within five generations of A; or if B is A direct relative of A, it is also possible.)
See AC code for specific explanation:
#include<bits/stdc++.h> #define inf 110000 using namespace std; map<string, int> mp;//string: name int: number int p[inf],cnt[inf],dx[inf],dy[inf],sex[inf]; string ming[inf], xing[inf]; //Save everyone's first and last names bool judge(int x, int y) { memset(cnt,0,sizeof(cnt)); memset(dx,0,sizeof(dx)); memset(dy,0,sizeof(dy)); cnt[x]=1,cnt[y]=1; while(p[x] != -1){ //If x has elders, it keeps cycling up until there are no elders cnt[p[x]]++; dx[p[x]] = dx[x] + 1; //How many generations if(p[x] == y) return false; //If the superior of x is equal to y, return directly and output No x = p[x]; } while(p[y] != -1){ cnt[p[y]]++; dy[p[y]] = dy[y] + 1; if(cnt[p[y]] > 1){ //>1. It indicates that p[y] is also the elder of x. judge how many generations and whether it reaches five generations if(dy[p[y]]>=4 && dx[p[y]] >= 4) return true; else return false; } y = p[y]; } return true; } int main(){ int n,m; cin>>n; getchar(); for(int i=1; i<=n; i++){ cin>>ming[i]>>xing[i]; mp[ming[i]]=i; //The name is unique, so change the name to number for easy processing int t=xing[i].size()-1; if(xing[i][t]=='m'||xing[i][t]=='n') sex[i]=1;//Male (name ending with m or sson) else sex[i]=-1; //female //Save the last name with the suffix removed, that is, the father's first name string s=""; if(xing[i][t]=='n'){ for(int j=0; j<t-3; j++) s+=xing[i][j]; }else if(xing[i][t]=='r'){ for(int j=0; j<t-6; j++) s+=xing[i][j]; } xing[i]=s; } memset(p,-1,sizeof(p));//Initially - 1, no elders for(int i=1; i<=n; i++){ if(mp[xing[i]]>0) p[i]=mp[xing[i]]; //p[i] indicates the number I and its father number } cin>>m; string s1,s2,s3,s4; while(m--){ cin>>s1>>s2>>s3>>s4; int x=mp[s1],y=mp[s3]; if(!sex[x]||!sex[y]) cout<<"NA"<<endl; //If sex[i] is 1, it is male, if it is - 1, it is female, if it is 0, it means there is no such person else if(sex[x]==sex[y])cout<<"Whatever"<<endl;//First, we need to judge whether it exists, and then we need to judge whether it is the same sex, otherwise we can't pass some tests else{ //If the opposite sex, judge whether they are close relatives if(judge(x, y)) cout<<"Yes"<<endl; else cout<<"No"<<endl; } } return 0; }
If the reader does not understand it thoroughly, refer to the following illustration:
Graphic reference link: https://blog.csdn.net/weixin_/article/details/88925108
Welcome to criticize and correct!!!