题目描述
如果A,B是C的父母亲,则A,B是C的parent,C是A,B的child,如果A,B是C的(外)祖父,祖母,则A,B是C的grandparent,C是A,B的grandchild,如果A,B是C的(外)曾祖父,曾祖母,则A,B是C的great-grandparent,C是A,B的great-grandchild,之后再多一辈,则在关系上加一个great-。
输入描述:
输入包含多组测试用例,每组用例首先包含2个整数n(0<=n<=26)和m(0<m<50), 分别表示有n个亲属关系和m个问题, 然后接下来是n行的形式如ABC的字符串,表示A的父母亲分别是B和C,如果A的父母亲信息不全,则用-代替,例如A-C,再然后是m行形式如FA的字符串,表示询问F和A的关系。
输出描述:
如果询问的2个人是直系亲属,请按题目描述输出2者的关系,如果没有直系关系,请输出-。 具体含义和输出格式参见样例.
示例1
输入
复制
3 2 ABC CDE EFG FA BE
输出
复制
great-grandparent -
其实本质相当于倒过来的二叉树
比如题目中的例子
A是BC的孩子,那么应该建立由B向A的链表和由C向A的链表,这样的目的是从任何一个节点向下遍历方向是唯一的,容易确定先后顺序
比如我想知道G和C是不是直系亲属,那么从G遍历下来的路径是GECA,这里面包含了C,所以G是C的爷爷(因为隔了两代)
如果判断G和D是不是直系亲属,从G向下遍历是GECA,从D遍历下来时DCA,注意,虽然有交集CA,但由于G的遍历中不含有D,D的遍历中不含有G,所以两者不是直接亲属
基于以上的思想,我们可以开一个map分别记录每一个人的指针,之后开一个vector,记录每人向下遍历的路径。
之后比如想知道B和G的关系,首先根据map找到B指针,根据指针找到vector中B的遍历路径,查找是否有G。如果有的话,证明B是G的前辈,按照代数输出parent即可。
如果没有,则反过来根据map找到G的指针,根据指针找到vector中G的遍历路径,查找是否有B,如果有证明B是G的孩子,根据代数输出child即可。
若也没有,则为-,即不是直系亲属
总结:是一道链表的好题目
#include<iostream>
#include<cstdio>
#include<queue>
#include<cmath>
#include<algorithm>
#include<cstring>
#include <sstream>
#include<map>
using namespace std;
struct data{
char id;
data* child;
data(char id):id(id),child(NULL){}
};
int find(vector<char> v,char text){
for(int i=0;i<v.size();i++){
if(v[i]==text){
return i;
}
}
return -1;
}
map<char,data*>mp;
int main(){
int num,ques;
cin>>num>>ques;
mp.clear();
for(char i='A';i<='Z';i++)
mp[i]=NULL;
while(num--){
char a[3];
cin>>a;
data* p1=mp[a[1]];
data* p2=mp[a[2]];
//如果map中没有这个人的指针位置,则需要存入map
//如果已经有了,即p1!=NULL时,表明之前已经存入map了,不用再次存储
if(p1==NULL){
p1=new data(a[1]);
mp[a[1]]=p1;
}
if(p2==NULL){
p2=new data(a[2]);
mp[a[2]]=p2;
}
data* p0=mp[a[0]];
if(p0==NULL){
p0=new data(a[0]);
mp[a[0]]=p0;
}
//如果缺少父母信息,则不存入数据
if(a[1]!='-')
p1->child=p0;
if(a[2]!='-')
p2->child=p0;
}
vector<char>v[26];
//记载每一个人的遍历路径,比如vector[0]表明A从上到下的遍历路径
for(int i=0;i<26;i++){
data* now=mp['A'+i];
while(now!=NULL){
v[i].push_back(now->id);
now=now->child;
}
}
while(ques--){
char temp[2];
cin>>temp;
char s1=temp[0];
char s2=temp[1];
int ans=find(v[s1-'A'],s2);
if(ans==-1){//从s1到s2找不到时,倒过来找试试,因为s1不是s2的前辈时,有可能s1是s2的后辈
ans=find(v[s2-'A'],s1);
if(ans==-1){//既不是前辈也不是后辈,则不是直系亲属
cout<<"-"<<endl;
}
else if(ans==1)
cout<<"child"<<endl;
else if(ans==2)
cout<<"grandchild"<<endl;
else {
for(int i=1;i<=ans-2;i++)
cout<<"great-";
cout<<"grandchild"<<endl;
}
}
else{
if(ans==1)
cout<<"parent"<<endl;
else if(ans==2)
cout<<"grandparent"<<endl;
else{
for(int i=1;i<=ans-2;i++)
cout<<"great-";
cout<<"grandparent"<<endl;
}
}
}
}