Problem:
Problem I: Cousin's Aunt

Sarah is a girl who likes reading books.

One day, she wondered about the relationship of a family in a mystery novel. The story said,

B is A’s father’s brother’s son, and

C is B’s aunt.

Then she asked herself, “So how many degrees of kinship are there between A and C?”

There are two possible relationships between B and C, that is, C is either B’s father’s sister or
B’s mother’s sister in the story. If C is B’s father’s sister, C is in the third degree of kinship to
A (A’s father’s sister). On the other hand, if C is B’s mother’s sister, C is in the fifth degree of
kinship to A (A’s father’s brother’s wife’s sister).

You are a friend of Sarah’s and good at programming. You can help her by writing a general
program to calculate the maximum and minimum degrees of kinship between A and C under
given relationship.

The relationship of A and C is represented by a sequence of the following basic relations: father,
mother, son, daughter, husband, wife, brother, sister, grandfather, grandmother, grandson,
granddaughter, uncle, aunt, nephew, and niece. Here are some descriptions about these relations:

X’s brother is equivalent to X’s father’s or mother’s son not identical to X.

X’s grandfather is equivalent to X’s father’s or mother’s father.

X’s grandson is equivalent to X’s son’s or daughter’s son.

X’s uncle is equivalent to X’s father’s or mother’s brother.

X’s nephew is equivalent to X’s brother’s or sister’s son.

Similar rules apply to sister, grandmother, granddaughter, aunt and niece.

In this problem, you can assume there are none of the following relations in the family: adoptions,
marriages between relatives (i.e. the family tree has no cycles), divorces, remarriages, bigamous
marriages and same-sex marriages.

The degree of kinship is defined as follows:

The distance from X to X’s father, X’s mother, X’s son or X’s daughter is one.

The distance from X to X’s husband or X’s wife is zero.

The degree of kinship between X and Y is equal to the shortest distance from X to Y
deduced from the above rules.

Input

The input contains multiple datasets. The first line consists of a positive integer that indicates
the number of datasets.

Each dataset is given by one line in the following format:

C is A(’s relation)*

Here, relation is one of the following:

father, mother, son, daughter, husband, wife, brother,
sister, grandfather, grandmother, grandson, granddaughter, uncle, aunt, nephew, niece.

An asterisk denotes zero or more occurance of portion surrounded by the parentheses. The
number of relations in each dataset is at most ten.

Output

For each dataset, print a line containing the maximum and minimum degrees of kinship separated
by exact one space. No extra characters are allowed of the output.

Sample Input

7
C is A’s father’s brother’s son’s aunt
C is A’s mother’s brother’s son’s aunt
C is A’s son’s mother’s mother’s son
C is A’s aunt’s niece’s aunt’s niece
C is A’s father’s son’s brother
C is A’s son’s son’s mother
C is A

Output for the Sample Input

5 3
5 1
2 2
6 0
2 0
1 1
0 0

Solution in C++ (judge verdict: Memory Limit Exceeded)

#include<iostream>
#include<sstream>
#include<queue>
#include<algorithm>
#include<map>
#include<vector>
using namespace std;
#define REP(i,b,n) for(int i=b;i<n;i++)
#define rep(i,n)   REP(i,0,n)
#define ALL(C)    (C).begin(),(C).end()
#define fir first
#define sec second
#define pb push_back
#define mp make_pair
#define BIT(i) (1<<(i))

typedef pair<int,int> pii;

enum{f=0,m,s,d,w,h};
enum{father=0,mother,son,daughter,husband,wife,brother,sister,grandfather,
       grandmother,grandson,granddaughter,uncle,aunt,nephew,niece};
const string name[]={"father", "mother", "son", "daughter", "husband", 
		     "wife", "brother","sister","grandfather","grandmother","grandson",
		     "granddaughter","uncle","aunt","nephew","niece"};
//const int inf = (1 << 20);
const int inf = 10000;

vector<int> path[16];
void makepath(){
  path[father].pb(BIT(f));
  path[mother].pb(BIT(m));
  path[son].pb(BIT(son));
  path[daughter].pb(BIT(d));
  path[husband].pb(BIT(h));
  path[wife].pb(BIT(w));
  //path[brother].pb(BIT(f)|BIT(m));path[brother].pb(BIT(s));
  path[brother].pb(BIT(f));path[brother].pb(BIT(s));
  //path[sister ].pb(BIT(f)|BIT(m));path[sister ].pb(BIT(d));
  path[sister ].pb(BIT(f));path[sister ].pb(BIT(d));
  path[grandfather].pb(BIT(f)|BIT(m));path[grandfather].pb(BIT(f));
  path[grandmother].pb(BIT(f)|BIT(m));path[grandmother].pb(BIT(m));
  //path[uncle].pb(BIT(f)|BIT(m));path[uncle].pb(BIT(f)|BIT(m));path[uncle].pb(BIT(s));
  path[uncle].pb(BIT(f)|BIT(m));path[uncle].pb(BIT(m));path[uncle].pb(BIT(s));
  //path[aunt].pb(BIT(f)|BIT(m));path[aunt].pb(BIT(f)|BIT(m));path[aunt].pb(BIT(d));
  path[aunt].pb(BIT(f)|BIT(m));path[aunt].pb(BIT(f));path[aunt].pb(BIT(d));
  //path[nephew].pb(BIT(f)|BIT(m));path[nephew].pb(BIT(s)|BIT(d));path[nephew].pb(BIT(s));
  path[nephew].pb(BIT(m));path[nephew].pb(BIT(s)|BIT(d));path[nephew].pb(BIT(s));
  //path[niece ].pb(BIT(f)|BIT(m));path[niece ].pb(BIT(s)|BIT(d));path[niece ].pb(BIT(d));
  path[niece ].pb(BIT(m));path[niece ].pb(BIT(s)|BIT(d));path[niece ].pb(BIT(d));
  path[grandson     ].pb(BIT(s)|BIT(d));path[grandson     ].pb(BIT(s));
  path[granddaughter].pb(BIT(s)|BIT(d));path[granddaughter].pb(BIT(d));
}

class Node{
public:
  Node(){};
  Node(int tnode,int tpnum,bool tmale):nodenum(tnode),pnum(tpnum),ismale(tmale){
    f=m=w=h=-1;s.clear();d.clear();
  }
  bool ismale;
  int f,m,w,h;
  vector<int> s,d;
  int nodenum;
  int pnum;
};


class st{
public:
  int now,cost;
  bool operator<(const st & a)const{
    return cost > a.cost;
  }
};
const int N = 455000;
int total=0;
bool isgoal[N];
Node all[N];

bool haschild(int val,int val2,int now,bool isson){
  if (isson){
    if (all[now].s.size() > 2)return true;
//     rep(i,all[now].s.size())
//       if (all[all[now].s[i]].nodenum == val && 
// 	  all[all[now].s[i]].pnum    == val2)
// 	return true;
  }else {
    if (all[now].d.size() > 2)return true;
//     rep(i,all[now].d.size()){
//       if (all[all[now].d[i]].nodenum == val &&
// 	  all[all[now].d[i]].pnum    == val2)
// 	return true;
//     }
  }
  return false;
}

void search(int n,int now,int *in,vector<int> &p,int pp,int cur,int prev){
  ///if (all[cur].d.size() > 10||
  //all[cur].s.size() > 10)
  //cout << now<<" " << pp << endl;
  //cout << now << " " << pp <<": " << cur <<" " << all[cur].nodenum<<" " << 
  //all[cur].d.size()<<" "<< all[cur].s.size() << endl;
  
  if (pp != p.size()){
    int np = p[pp];
    if (np&BIT(f)){
      if (all[cur].f == -1){
	if (all[cur].m != -1 && all[all[cur].m].h != -1){
	  all[cur].f = all[all[cur].m].h;
	  if (all[cur].ismale)all[all[cur].f].s.pb(cur);
	  else all[all[cur].f].d.pb(cur);
	}else {
	  all[cur].f=total;
	  all[total]=Node(now,pp,true);
	  if (all[cur].ismale)all[total].s.pb(cur);
	  else all[total].d.pb(cur);
	  if (all[cur].m != -1){
	    all[total     ].w=all[cur].m;//define wife
	    all[all[cur].m].h=total;//define husband;
	    all[total].d=all[all[cur].m].d;
	    all[total].s=all[all[cur].m].s;
	  }
	  total++;
	}
      }
      search(n,now,in,p,pp+1,all[cur].f,cur);
    }

    if (np&BIT(m)){
      if (all[cur].m == -1){
	if (all[cur].f!=-1 && all[all[cur].f].w != -1){
	  all[cur].m=all[all[cur].f].w;
	  if (all[cur].ismale)all[all[cur].m].s.pb(cur);
	  else all[all[cur].m].d.pb(cur);
	}else {
	  all[cur].m=total;
	  all[total]=Node(now,pp,false);
	  if (all[cur].ismale)all[total].s.pb(cur);
	  else all[total].d.pb(cur);
	  if (all[cur].f != -1){
	    all[all[cur].f].w=total;
	    all[total     ].h=all[cur].f;
	    all[total].s=all[all[cur].f].s;
	    all[total].d=all[all[cur].f].d;
	  }
	  total++;
	}
      }
      search(n,now,in,p,pp+1,all[cur].m,cur);
    }
    if (np&BIT(s)){
      if (!haschild(now,pp,cur,true)){
	all[cur].s.pb(total);
	all[total]=Node(now,pp,true);
	if (all[cur].ismale){//cur is male
	  all[total].f=cur;
	  if (all[cur].w != -1)all[total].m=all[cur].w;
	}
	else {//cur is female
	  all[total].m=cur;
	  if (all[cur].h != -1)all[total].f=all[cur].h;
	}
	total++;
      }
      rep(i,all[cur].s.size()){
	if (all[cur].s[i]!=prev)
	search(n,now,in,p,pp+1,all[cur].s[i],cur);
      }
    }

    if (np&BIT(d)){
      if (!haschild(now,pp,cur,false)){
	all[cur].d.pb(total);
	all[total]=Node(now,pp,false);
	if (all[cur].ismale){// cur is male
	  all[total].f=cur;
	  if (all[cur].w != -1)all[total].m=all[cur].w;
	}else {//cur is female
	  all[total].m=cur;
	  if (all[cur].h != -1)all[total].f=all[cur].h;
	}
	total++;
      }
      rep(i,all[cur].d.size()){
	if (all[cur].d[i] != prev)
	search(n,now,in,p,pp+1,all[cur].d[i],cur);
      }
    }

    if (np&BIT(w)&& all[cur].ismale){
      if (all[cur].w == -1){
	all[cur].w=total;
	all[total]=Node(now,pp,false);
	all[total].h=cur;
	all[total].d=all[cur].d;
	all[total].s=all[cur].s;
	total++;
      }
      search(n,now,in,p,pp+1,all[cur].w,cur);
    }

    if (np&BIT(h) && !all[cur].ismale){
      if (all[cur].h == -1){
	all[cur].h=total;
	all[total]=Node(now,pp,true);
	all[total].w=cur;
	all[total].d=all[cur].d;
	all[total].s=all[cur].s;
	total++;
      }
      search(n,now,in,p,pp+1,all[cur].h,cur);
    }
    return;
  }
  if (now == n){
    isgoal[cur]=true;
    return;
  }else {
    search(n,now+1,in,path[in[now]],0,cur,-1);
  }
}


vector<pii> edge[N]; //to,cost
void makegraph(){
  rep(i,total){
    if (all[i].m != -1)edge[i].pb(mp(all[i].m,1));
    if (all[i].f != -1)edge[i].pb(mp(all[i].f,1));
    if (all[i].w != -1)edge[i].pb(mp(all[i].w,0));
    if (all[i].h != -1)edge[i].pb(mp(all[i].h,0));
    rep(j,all[i].s.size())edge[i].pb(mp(all[i].s[j],1));
    rep(j,all[i].d.size())edge[i].pb(mp(all[i].d[j],1));
  }

  /*
   rep(i,total){
     cout << i <<":" << all[i].ismale << endl;
     if (all[i].m != -1)cout << "Mother " << all[i].m << endl;
     if (all[i].f != -1)cout << "father " << all[i].f << endl;
     if (all[i].w != -1)cout << "Wife " << all[i].w << endl;
     if (all[i].h != -1)cout << "husband "<<all[i].h << endl;
     cout << "son ";rep(j,all[i].s.size())cout << all[i].s[j] << " ";
     cout << endl;
     cout <<"daughter";
     rep(j,all[i].d.size())cout << all[i].d[j] <<" " ;
     cout << endl;
     cout << "end " << endl;
   }
  */
}

short cost[N];
pii dijkstra(int n){
  makegraph();
  rep(i,n)cost[i]=inf;
  cost[0]=0;
  priority_queue<st> Q;
  Q.push((st){0,0});
  while(!Q.empty()){
    st now = Q.top();Q.pop();
    if (now.cost != cost[now.now])continue;
    rep(i,edge[now.now].size()){
      int nex=edge[now.now][i].fir;
      int nec=now.cost+edge[now.now][i].sec;
      if (nec < cost[nex])cost[nex]=nec,Q.push((st){nex,nec});
    }
  }
  pii ret(inf,-inf);
  rep(i,n){
    if (isgoal[i] && cost[i] != inf){
      ret.fir=min(ret.fir,(int)cost[i]);
      ret.sec=max(ret.sec,(int)cost[i]);
    }
  }

  /*
  rep(i,n)cout << i <<" " << isgoal[i] <<" "<<
    cost[i] << endl;
  */

  return ret;
}

void parse(int &p,int *in,string &a,map<string,int> &M){
  p=0;
  rep(i,a.size()-1){
    if (a[i] == '\'' && a[i+1] == 's')a[i]=' ',a[i+1]=' ';
  }
  stringstream sin(a);
  string tmp;
  rep(i,3)sin>>tmp;
  while(sin>>tmp)in[p++]=M[tmp];
}

main(){
  makepath();
  map<string,int> M;
  rep(i,16)M[name[i]]=i;
  vector<int> dummy;
  int te;
  string tmp;
  cin>>te;getline(cin,tmp);
  while(te--){
    getline(cin,tmp);
    int p=0,in[10];
    pii ans1(inf,-inf),ans2(inf,-inf);
    parse(p,in,tmp,M);
    total=1;

    //    rep(i,N)edge[i].clear(),isgoal[i]=false,all[i]=Node(0,-1,true);
    all[0]=Node(0,-1,true);
    search(p,0,in,dummy,0,0,-1);
    ans1=dijkstra(total);
    //cout <<"size of node " << total <<" ";
    rep(i,total)edge[i].clear(),isgoal[i]=false,all[i]=Node(0,-1,true);
    total=1;
    all[0]=Node(0,-1,false);
    search(p,0,in,dummy,0,0,-1);
    ans2=dijkstra(total);

    rep(i,total)edge[i].clear(),isgoal[i]=false,all[i]=Node(0,-1,true);
    //cout << total << endl;
    //cout <<"ans1 " <<  ans1.sec <<" " << ans1.fir << endl;
    //cout <<"ans2 " <<  ans2.sec <<" " << ans2.fir << endl;
    //    cout << max(ans1.sec,ans2.sec)<<" " << min(ans1.fir,ans2.fir) << 
    //      " " << total << endl;
    cout << max(ans1.sec,ans2.sec)<<" " << min(ans1.fir,ans2.fir) <<endl;
  }
  return false;
}



/*

size of node 1 1
0 0
size of node 7 7
3 3
size of node 18 18
4 0
size of node 44 44
5 1
size of node 121 121
6 0
size of node 298 298
7 1
size of node 896 896
8 0
size of node 2490 2490
9 1


*/