其实本质相当于倒过来的二叉树

比如题目中的例子

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;
            }

        }
    }
}