4-1-7 binary tree and its traversal genealogy processing (30 points)

Anthropological research is very interested in families, so researchers collected some family genealogies for research. In the experiment, the family tree is processed by computer. To achieve this, the researchers converted the genealogy into a text file. The following is an example of a genealogy text file:

John
  Robert
    Frank
    Andrew
  Nancy
    David

In the genealogy text file, each line contains a person's name. The name in the first line is the earliest ancestor of the family. The genealogy contains only the descendants of the earliest ancestors, and their husbands or wives do not appear in the genealogy. Each child indents two more spaces than their parents. Taking the above genealogy text file as an example, John, the earliest ancestor of the family, has two children Robert and Nancy, Robert has two children Frank and Andrew, and Nancy has only one child David.

In the experiment, the researchers also collected family documents and extracted statements about the relationship between two people from the family tree. The following is an example of the statement statement of the relationship in the Genealogy:

John is the parent of Robert
Robert is a sibling of Nancy
David is a descendant of Robert

Researchers need to judge whether each statement is true or false. Please write a program to help researchers judge.

Input format:

Input first gives two positive integers N (2 ≤ N ≤ 100) and m (≤ 100), where N is the number of names in the genealogy and M is the number of statements in the genealogy. Each line of input shall not exceed 70 characters.

The name string consists of no more than 10 English letters. There is no indented space before the name given in the first line of the family tree. Other names in the genealogy shall be indented by at least 2 spaces, that is, they are the descendants of the earliest ancestor in the Genealogy (the name given in the first line). If a name in the genealogy is indented by k spaces, the name in the next line shall be indented by k+2 spaces at most.

The same name will not appear twice in a genealogy, and the name that does not appear in the genealogy will not appear in the statement. The format of each statement is as follows, where X and Y are different names in the Genealogy:

X is a child of Y
X is the parent of Y
X is a sibling of Y
X is a descendant of Y
X is an ancestor of Y

Output format:

For each statement in the test case, True is output in one line. If the statement is True, or False, if the statement is False.

Input sample:

6 5
John
  Robert
    Frank
    Andrew
  Nancy
    David
Robert is a child of John
Robert is an ancestor of Andrew
Robert is a sibling of Nancy
Nancy is the parent of Frank
John is a descendant of Andrew

Output example:

True
True
True
False
False

The first time I saw this question was in the winter vacation. At that time, I just learned trees, and I couldn't figure out the binary tree. Where would this kind of multi fork tree problem be? So during the winter vacation, I was trapped in Jianshu.

Many attempts were made to solve the problem during the winter vacation, which fail ed. (I'm too good)

After all, I still have to face this problem. Seeing this problem again is this assignment.

The following is the practice of sudden inspiration last night (the code knocked today): (achievement + consideration of situation)

#include<bits/stdc++.h>
using namespace std;
string name[110];
map<string,string>fa; //Because the number of child nodes is uncertain, there is no way to build a tree with the method of binary tree. Here, the method of map is adopted, that is, the idea of merging and searching sets
int main(){
    //freopen("alltxt.txt","r",stdin);
    int n,m;
    cin>>n>>m;
    getchar();//getline will read the carriage return. Here is a point of attention
    string s;
    
    //Build a tree
    for(int i=0;i<n;i++){
        getline(cin,s);
        int kong=count(s.begin(),s.end(),' ');
        if(kong==0){
            fa[s]="#"; //The parents of ancestors can be recorded as "#"
            name[0]=s;
        }
        else{
            s=s.erase(0,kong); //Remove spaces
            //The following two sentences of code are what I didn't think of when I did it in winter vacation - the second point that trapped me in winter vacation
            name[kong/2]=s; //It has the function of temporarily recording the parents of the previous level, and the same level is covered
            fa[s]=name[kong/2-1]; //Record parents
        }
    }
    
    //Consider by case
    string op;
    for(int i=0;i<m;i++){
        getline(cin,op);
        //Find a way to separate x and y, and then proceed to the next operation. Here, the interception of string is used 
        //This is an annoying place
        string x=op.substr(0,op.find(" is"));
        string y=op.substr(op.find("of ")+3,op.length());
        //Looking for y's child
        //This situation is in line with our achievements - to record our parents
        if(op.find("child")!=string::npos){
            if(fa[x]==y)cout<<"True"<<endl;
            else cout<<"False"<<endl;
        }
        //Find y's parents, the inverse process of the previous case
        //This situation is in line with our achievements - to record our parents
        else if(op.find("parent")!=string::npos){
            if(fa[y]==x)cout<<"True"<<endl;
            else cout<<"False"<<endl;
        }
        //Looking for y's brothers and sisters
        //Just judge whether the parents of x and y are the same. This situation is in line with our goal of building a record of parents
        else if(op.find("sibling")!=string::npos){
            if(fa[x]==fa[y])cout<<"True"<<endl;
            else cout<<"False"<<endl;
        }
        //Looking for y's descendants
        //Since our fa[y] represents Y's parents, which is not conducive to finding descendants. Considering that the two statements "Y's descendants are x" and "X's ancestors are y" are equivalent, we can consider starting with X as long as we know whether X's ancestors are y. this is consistent with the next case - finding Y's ancestors. Just change the code a little (I use this method), or merge the two cases.
        else if(op.find("descendant")!=string::npos){
            int flag=1;
            while(x!="#") {/ / keep looking until you find the head
                if(fa[x]==y){
                    cout<<"True"<<endl;
                    flag=0;
                    break;
                }
                x=fa[x];
            }
            if(flag)cout<<"False"<<endl;  //I didn't find the head
        }
        //Find y's ancestors
        //This situation is in line with our achievements - to record our parents
        else if(op.find("ancestor")!=string::npos){
            int flag=1;
            while(y!="#"){
                if(fa[y]==x){  //I've been looking for it since I didn't find the head
                    cout<<"True"<<endl;
                    flag=0;
                    break;
                }
                y=fa[y];
            }
            if(flag)cout<<"False"<<endl;  //I didn't find the head
        }
    }
    return 0;
}

Added by lkq on Wed, 09 Feb 2022 21:52:15 +0200