Time Limit: 3.000 seconds
Time Limit: 3.000 seconds
Background
Background
Expression trees, B and B * trees, red-black trees, quad trees, PQ trees; trees play a significant role in your domains of computer science. sometimes the name of a problem may indicate that trees are used when they are not, as in the artificial intelligence planning problem traditionally called the monkey and bananas problem. sometimes trees may be used in a problem whose name gives no indication that trees are involved, as in the Huffman code.
Expression Tree, B/B * tree, red/black tree, quad-tree, PQ tree ......, Tree plays an important role in many fields of computer science. The names of some problems indicate that they use a tree structure. For example, the intelligent planning problem is traditionally called the "monkey and banana" problem. Some problems do apply to the tree structure, but it is not shown in its name, such as The Harman encoding.
This problem involves determining how pairs of people who may be part of a "family tree" are related.
This problem is to determine whether two people have kinship in a family tree.
The Problem
Problem
given a sequence of child-parent pairs, where a pair consists of the child's name followed by the (single) parent's name, and a list of query pairs also expressed as two names, you are to write a program to determine whether the query pairs are related. if the names comprising a query pair are related the program shoshould determine what the relationship is. consider academic advisees and advisors As exemplars of such a single parent genealogy (we assume a single advisor, I. E ., no co-Advisors ).
given a series of "child-parent" name pairs, each pair of names is a child, the latter is the parent (single parent ). Then, a series of name pairs are given to indicate the names of two people. You need to write a Program to determine whether the two names to be checked have kinship in the family tree. If you are sure that there is a kinship between the two names to be checked, you need to specify the relationship. The relationship between students and mentors in a university can be considered as an example of a single-parent lineage (we assume that each student has only one tutor without mutual Guidance ).
In this problem the child-parent pair p q denotes that p is the child of Q. In determining relationships between names we use the following definitions:
In this case, "child-parent" indicates that p q is the child of Q. In the process of determining the name relationship, we have the following inductive definitions:
- P is a 0-descendent of Q (respectively 0-ancestor) if and only if the child-parent pair p q (respectively q p) appears in the input sequence of child-parent pairs.
P is the first descendant of Q. if and only if there is a "child-parent" pair of p q in the input sequence, the relationship between p and q is "child-parent.
- P is a K-descendent of Q (respectively K-ancestor) if and only if the child-parent pair p r (respectively q r) appears in the input sequence and R is a (k-1)-descendent of Q (respectively P is a (k-1)-ancestor of R ).
P is the k-th descendant of Q. if and only if R is the (k-1) descendant of Q, and there is a "sub-parent" to p r in the input sequence, the relationship between P and R is "sub-parent.
For the purposes of this problem the relationship between a person P and a person Q is expressed as exactly one of the following four relations:
In this case, the kinship between p and q can only be one of the following four relationships:
-
- Child -- grand child, great grand child, great grand child, etc.
By definition P is the "child" of Q if and only if the pair p q appears in the input sequence of child-parent pairs (I. E ., P is a 0-descendent of Q); P is the "grand child" of Q if and only if p is a 1-descendent of Q; and
Sub-relationships-including Sun's "grand child", Zeng Sun's "great grand child", and Xuan Sun's "great grand child.
According to the definition, p is the "child" of Q. if and only if there is a "child-parent" pair of p q in the input sequence, it is pointed out that they are "child-parent" relationships (that is, p is the 0th descendant of Q); P is the "grand child" (Sun) of Q) if and only when P is the 1st descendant of Q, and:
If and only if p is an (n + 1)-descendent of Q.
If and only when P is the Nth (n + 1) descendant of Q.
- Parent -- grand parent, great grand parent, great grand parent, etc.
Parent relationship-including grandfather "grand parent", great grandfather "great grand parent", and high grandfather "great grand parent.
By definition P is the "parent" of Q if and only if the pair Q p appears in the input sequence of child-parent pairs (I. E ., P is a 0-ancestor of Q); P is the "grand parent" of Q if and only if p is a 1-ancestor of Q; and
The definition of the parent relationship corresponds to the child relationship. For more information, see "child relationship ".
If and only if p is an (n + 1)-ancestor of Q.
- Cousin -- 0th cousin, 1st cousin, 2nd cousin, etc.; cousins may be once removed, twice removed, three times removed, etc.
Tang Qin-0th "0th cousin", 1st "1st cousin", and 2nd "2nd cousin ". The Church has a generational relationship, namely, the first generation, the second generation, and the third generation.
The family relationship in the United States is very different from that in China. N in the "nth cousin" refers to the generation of a long man in two and the recent common ancestor minus 1. For example, if you and your aunt (father and sister) have a recent ancestor of grandfather, the relationship is 0th cousin. The recent ancestor of you and your cousin (aunt's son) is also a grandfather, the relationship is 1st cousin; the relationship between you and your sister-in-law is 2nd cousin. The Gender m of the two cousin relationships is represented by "cousin removed m .)
By definition p and q are "cousins" if and only if they are related (I. E ., there is a path from P to Q in the implicit undirected parent-child tree ). let R represent the least common ancestor of p and q (I. E ., no descendent of R is an ancestor of both p and q), where p is an M-descendent of R and Q is an N-descendent of R.
According to the definition, p and q are cousins, and only when they have kinship (that is, a path from P to Q is hidden in the family tree ). So that R represents the recent co-ancestor of p and q (that is, no descendant of R is also the co-ancestor of p and q), and P is the M descendant of R, Q is the nth descendant of R.
Then, by definition, cousins p and q are "kth cousins" if and only if k = min (n, m), and, also by definition, p and q are "cousins removed J times" if and only if J = | n-M |.
According to the definition, the cousin p and q are "kth cousin" Only when k = min (n, m ). P and q are "cousin removed J times" only when J = | n-M |.
-
- Sibling -- 0th cousins removed 0 times are "Siblings" (they have the same parent ).
Compatriot-"0th cousins removed 0 times" is a compatriot "siblings" (they have a common parent ).
The input
Input
the input consists of parent-child pairs of names, one pair per line. each name in a pair consists of lower-case alphabetic characters or periods (used to separate first and last names, for example ). child names are separated from parent names by one or more spaces. parent-child pairs are terminated by a pair whose first component is the string "no. child ". such a pair is not to be considered A parent-child pair, but only as a delimiter to separate the parent-child pairs from the query pairs. there will be no circular relationships, I. E ., no name P can be both an ancestor and a descendent of the same name Q.
the input consists of a series of name pairs, each of which occupies an exclusive row. The names in each pair are composed of lowercase letters and periods (for example, names can be separated by names. And the parent are separated by one or more spaces. When the input name is "No. Child", the input is ended. The Terminator is only used to separate the child-parent pair and the pending pair. The program cannot treat it as a child-parent pair. There is no circular relationship in the input, that is, no name P can be the descendant and ancestor of Q.
The parent-child pairs are followed by a sequence of query pairs in the same format as the parent-child pairs, I. E ., each name in a query pair is a sequence of lower-case alphabetic characters and periods, and names are separated by one or more spaces. query pairs are terminated by end-of-file.
The "child-parent" pairs are to be checked below. The format is the same as that of the "child-parent" pair. That is, the names in each pending pair are composed of lowercase letters and periods, two names are separated by one or more spaces. The input to be checked is ended by EOF.
There will be a maximum of 300 different names overall (parent-child and query pairs). All names will be fewer than 31 characters in length. There will be no more than 100 query pairs.
A total of 300 different names can appear (including "child-parent" and "to be queried ). All names must be less than 31 characters long. A maximum of 100 objects to be queried.
The output
Output
For each query-pair p q of names the output shocould indicate the relationship P is-the-relative-of Q by the appropriate string of the form
For each name to be checked, the output form of the following columns is required to indicate the relationship between p and q.
- Child, grand child, great grand child, great... great grand child
- Parent, grand parent, great grand parent, great... great grand parent
- Sibling
- N cousin removed m
- No relation
If an M-cousin is removed 0 times then only M cousin shoshould be printed, I. E ., removed 0 shocould not be printed. do not print St, Nd, RD, th after the numbers.
If an "m cousin" is separated by 0 generations, you only need to print "m cousin", that is, "removed 0" cannot appear in the output ". Do not add suffixes such as "St", "nd", "RD", and "th" after any number.
Sample Input
Input example
Alonzo. Church Oswald. Veblen
Stephen. Kleene Alonzo. Church
Dana. Scott Alonzo. Church
Martin. Davis Alonzo. Church
Pat. Fischer Hartley. Rogers
Mike Paterson David. Park
Dennis. Ritchie Pat. Fischer
Hartley. Rogers Alonzo. Church
Les. Valiant Mike. Paterson
Bob. Constable Stephen. Kleene
David. Park Hartley. Rogers
No. Child No. Parent
Stephen. Kleene Bob. Constable
Hartley. Rogers Stephen. Kleene
Les. Valiant Alonzo. Church
Les. Valiant Dennis. Ritchie
Dennis. Ritchie Les. Valiant
Pat. Fischer Michael. Rabin
Sample output
Output example
Parent
Sibling
Great great grand child
1 cousin removed 1
1 cousin removed 1
No relation
Analysis
Analysis
This is a typical example of LCA (recent common ancestor)Algorithm. According to the characteristics of this question, it is natural to convert the LCA question to the rqm question. The efficient algorithms for conversion algorithms and rqmArticle.
According to the requirements of the question, a child can only have one parent (we assume a single advisor, I. e., no co-Advisors). Therefore, there are many solutions to this question. However, it is very difficult to judge the data used.One child, multiple fathers. If you ignore such illegal input, you will get wa. The program must be able to "correctly" handle such exceptions, but the handling method is not provided.
In fact, the processing method is irregular, so that the conversion rqm Algorithm without considering multiple parent cases is forced to run in such abnormal input, the result is the so-called "correct" result. If you accidentally select an algorithm that is different from the operator's thinking, no matter how foolproof the program is written, no matter how you handle the situation of multiple fathers, you can only get wa.
I have been stuck on this question for a long time because my efficient algorithm cannot meet the abnormal requirements of the person who asked the question. I am very disgusted with this question! Tears:You must use an algorithm that converts the LCA question to the rmq question. All other algorithms are wa.!
Solution
Answer
# Include <algorithm> # include <iostream> # include <map> # include <vector> # include <string> using namespace STD; struct node {int NPAR; int NPOs; vector <int> Chi ;}; vector <node> tree; // stores the rqm sequence and depth vector <int> order, depth; // create an rqm table from the tree and use the recursive void buildrmqtable (INT nnode, int ndepth) {// enter the current node and store its number and depth order. push_back (nnode); depth. push_back (ndepth); node & node = tree [nnode]; // This node is repeated for the first time, recording the node position in the table. NPOs = N Ode. NPOs =-1? (Order. size ()-1): node. NPOs; // The Standard deep sample method of the Multi-Cross Tree, which sequentially accesses all subnodes for (vector <int>: iterator I = node. chi. begin (); I! = Node. chi. end ();) {buildrmqtable (* I ++, ndepth + 1); // return to the current node and store its number and depth order. push_back (nnode); depth. push_back (ndepth) ;}/// main function int main (void) {// name hashmap <string, int> nametbl; // initial value of the new node, parent:-1, rmq table location is-1 node newnode = {-1,-1}; // enter all the names in a loop, str1 is a child, str2 is the parent for (string str1, str2; cin> str1> str2 & str1! = "No. child ";) {// If (nametbl. end () = nametbl. find (str2) {nametbl [str2] = tree. size (); tree. push_back (newnode);} If (nametbl. end () = nametbl. find (str1) {nametbl [str1] = tree. size (); tree. push_back (newnode);} // create a parent-child relationship tree [nametbl [str2]. chi. push_back (nametbl [str1]); tree [nametbl [str1]. NPAR = nametbl [str2];} // to avoid the occurrence of "Multi-Tree", create a virtual root and put it in the tree at the end of the list. push_back (newnode); // All nodes in the example for (vector <node> :: Iterator I = tree. Begin (); I! = Tree. end ()-1; ++ I) {// find the node without a parent, that is, the node with the parent-1 if (I-> NPAR =-1) {// set the parent node to the total root I-> NPAR = tree. size ()-1; // Add the node tree to the subnode list of the total root. back (). chi. push_back (I-tree. begin () ;}}// recursively create the rmq table buildrmqtable (tree. size ()-1, 0); // cyclically input each group of queries for (string str1, str2; CIN >>> str1 >> str2;) {Map <string, int>: iterator I1 = nametbl. find (str1); Map <string, int>: iterator I2 = nametbl. find (str2); // if either of the two sub-names has no record, it is considered irrelevant if (I1 = Nametbl. end () | I2 = nametbl. end () {cout <"no relation" <Endl; continue;} // obtain the position of two sub-names in the query table int n1 = tree [I1-> second]. NPOs, n2 = tree [I2-> second]. NPOs; // If the holding position is small, the former if (depth [N1]> depth [n2]) {swap (N1, N2);} // rqm query vector <int> :: iterator ianc = min_element (depth. begin () + min (N1, N2), depth. begin () + max (N1, N2) + 1); // If the smallest and most common ancestor (LCS) is the total root, it is considered unrelated if (tree [order [ianc-depth. begin ()]. NPAR =-1) {cout <"No relation" <Endl; continue;} // nremoved is an interval algebra, ncousin is the minimum int nremoved = depth [n2]-depth [N1]; int ncousin = depth [N1]-* ianc; // If (ncousin = 0) {for (; nremoved> 2; -- nremoved) {cout <"great ";} if (nremoved> 1) {cout <"grand" ;}cout <(tree [I1-> second]. NPOs = N1? "Parent": "child") <Endl ;}// the LCS is the parent else if (ncousin = 1 & nremoved = 0) {cout <"sibling" <Endl ;}// cousin else {cout <ncousin-1 <"cousin"; if (nremoved> 0) {cout <"removed" <nremoved;} cout <Endl ;}} return 0 ;}