题目描述
The scientists working at the Family Genetics Institute are tracing the spread of a hereditary disease through family trees. They have started by listing the family members that have the disease, and the parent who passed the disease on to each child (we will assume that each child gets the disease from only one parent). However, the scientists are confused about the names of different family relationships. Parents, grandparents, and siblings they have a handle on. But a relationship like “third cousin, twice removed” has been hard for them to wrap their heads around. After much discussion they came up with some definitions that cleared things up.

Suppose we have two people conveniently named A and B and their closest common ancestor is named C (what are the odds!). We say that A is m generations removed from C  if there are m direct descendants from C ending with A. Thus if A is the daughter of C she is 1 generation removed; if she is the granddaughter of C she is 2 generations removed, and so on. Any person is 0 generations removed from themselves.

Now let A be m generations removed from C and B be n generations removed from C where m≤n. We can determine the relationship between A and B using the following rules:

1.if m=0 then B is the child of A if n=1 or the greatn−2 grandchild of A if n>1.

2.if 0<m=n then A and B are siblings if n=1 or (n−1)-th cousins if n>1.

3.if 0<m<n then A and B are (m−1)-th cousins (n−m) times removed.

Notice that if m=1 and n=2 we get the interestingly named “0th cousins, 1 time removed” for the relationships we typically describe as “aunt/uncle” or “niece/nephew”.

Figure 1 below shows some examples for two new people named (what else) D and E.

The scientists have given you the description of a family tree and pairs of people in the tree and have asked you to determine the relationships between members of each pair.

输入
Input begins with a line containing two positive integers t p (t≤100,p≤1000) specifying the number of tree descriptions (described below) and the number of query pairs. Following these are t lines, each with one tree description. Each tree description will be of the form s0 d s1 s2…sd indicating that person s0 has d children named s1 through sd. All names are unique and contain only alphabetic characters. Tree descriptions may be given in any order (i.e., the root of the entire tree may not necessarily be in the very first tree description). No name will appear more than once as s0 in the tree descriptions. All the tree descriptions will combine to form exactly one tree, and the tree will have at least 2 nodes and at most 100 nodes.

Following this are p lines of the form si sj where si≠sj and both names are guaranteed to be in the tree.
输出
Output the relationship for each pair of people, one per line, using the formats shown in Figure 1. Always output si’s name first for each pair except when sj is the direct descendant of si (as in the first example in Figure 1). For the n-th ordinal number output nth except for n=1,2,3,21,22,23,31,32,33,… in which case you should output 1st, 2nd, 3rd, 21st, 22nd, 23rd, 31st, 32nd, 33rd, etc. Also be sure to use times for all times removed except one, where you should use the word time.
样例输入 Copy
【样例1】
4 5
Horatio 1 Irene
Chris 2 Gina Horatio
Alice 3 Dan Emily Frank
Bob 2 Alice Chris
Irene Bob
Dan Frank
Chris Emily
Alice Chris
Dan Irene
【样例2】
4 6
A 4 B C D E
H 3 I J K
C 2 F G
D 1 H
G C
H A
F G
F H
F K
B K
样例输出 Copy
【样例1】
Irene is the great grandchild of Bob
Dan and Frank are siblings
Chris and Emily are 0th cousins, 1 time removed
Alice and Chris are siblings
Dan and Irene are 1st cousins, 1 time removed
【样例2】
G is the child of C
H is the grandchild of A
F and G are siblings
F and H are 1st cousins
F and K are 1st cousins, 1 time removed
B and K are 0th cousins, 2 times removed

思路:
对于每个点存储他的父节点,直接暴力找两个点的LCA模拟就好。
有一个坑点就是关于英文序数词的输出:
11,12,13后缀是th
垃圾题目
代码:

#pragma
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, ll>PLL;
typedef pair<int, int>PII;
typedef pair<double, double>PDD;
#define
inline ll read()
{
ll x = 0, f = 1;
char ch = getchar();
while(ch < '0' || ch > '9')
{
if(ch == '-')f = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9')
{
x = x * 10 + ch - '0';
ch = getchar();
}
return x * f;
}
#define
#define
#define
#define
#define
#define
#define
ll ksm(ll a, ll b, ll p)
{
ll res = 1;
while(b)
{
if(b & 1)res = res * a % p;
a = a * a % p;
b >>= 1;
}
return res;
}
const int inf = 0x3f3f3f3f;
#define
const double eps = 1e-8;
const int maxn =1e6+7;
map<string,int>mp;
int idx=1;
int fa[maxn];
int cul(string s){
if(!mp[s]) mp[s]=idx++;
return mp[s];
}
int vis[maxn];
string cul3(int x){
if(x==0) return "0";
int cnt =0 ;
int num[22];
while(x) num[++cnt] = x%10,x/=10;
reverse(num+1,num+1+cnt);
string temp="";
for(int i=1 ;i<=cnt; i++) {
char c = '0' +num[i];
temp = temp + c;
}
return temp;
}
string cul1(int x){
if(x>=11&&x<=13){
return cul3(x)+"th";
}
if(x%10==1) return cul3(x)+"st";
else if(x%10==2) return cul3(x)+"nd";
else if(x%10==3) return cul3(x)+"rd";
else return cul3(x)+"th";
}
string cul2(int x){
if(x==1) return "1 time";
string res=cul3(x);
res=res+" times";
return res;
}


int main(){
int n=read,m=read;
for(int i=1;i<=n;i++){
string s;cin>>s;
int fas=cul(s);
int k=read;
for(int j=1;j<=k;j++){
cin>>s;
int t=cul(s);
fa[t]=fas;
}
}
///for(auto it:mp)
/// cout<<it.first<<" "<<it.second<<endl;
for(int i=1;i<=m;i++){
string s1,s2;
cin>>s1>>s2;
int ts1=cul(s1),ts2=cul(s2);
memset(vis,0,sizeof vis);
int cnt1=0,cnt2=0;
while(1){
if(!ts1) break;
vis[ts1]=++cnt1;
ts1=fa[ts1];
}
int pos=-1;
while(1){
pos=ts2;
if(vis[ts2]) break;
cnt2++;
ts2=fa[ts2];
}
cnt1=vis[pos]-1;
///cout<<pos<<" "<<cnt1<<" "<<cnt2<<endl;
if(cnt1==0||cnt2==0){
if(cnt1==0){
if(cnt2==1){
cout<<s2<<" is the child of "<<s1<<endl;
}
else{
cout<<s2<<" is the ";
for(int ii=1;ii<=cnt2-2;ii++)
cout<<"great ";
cout<<"grandchild of "<<s1<<endl;
}
}
else{///cnt2==0
if(cnt1==1){
cout<<s1<<" is the child of "<<s2<<endl;
}
else{
cout<<s1<<" is the ";
for(int ii=1;ii<=cnt1-2;ii++)
cout<<"great ";
cout<<"grandchild of "<<s2<<endl;
}
}
}
else if(cnt1==cnt2){
if(cnt1==1)
cout<<s1<<" and "<<s2<<" are siblings"<<endl;
else
cout<<s1<<" and "<<s2<<" are "<<cul1(cnt1-1)<<" cousins"<<endl;
}
else{
if(cnt1<cnt2){
cout<<s1<<" and "<<s2<<" are "<<cul1(cnt1-1)<<" cousins, "<<cul2(cnt2-cnt1)<<" removed"<<endl;
}
else{
swap(cnt1,cnt2);
cout<<s1<<" and "<<s2<<" are "<<cul1(cnt1-1)<<" cousins, "<<cul2(cnt2-cnt1)<<" removed"<<endl;
}
}

}
return 0;
}
/**
Irene is the great grandchild of Bob
Dan and Frank are siblings
Chris and Emily are 0th cousins, 1 time removed
Alice and Chris are siblings
Dan and Irene are 1st cousins, 1 time removed
*/