人类学研究对于家族很感兴趣,于是研究人员搜集了一些家族的家谱进行研究。实验中,使用计算机处理家谱。为了实现这个目的,研究人员将家谱转换为文本文件。下面为家谱文本文件的实例:
John
Robert
Frank
Andrew
Nancy
David
家谱文本文件中,每一行包含一个人的名字。第一行中的名字是这个家族最早的祖先。家谱仅包含最早祖先的后代,而他们的丈夫或妻子不出现在家谱中。每个人的子女比父母多缩进2个空格。以上述家谱文本文件为例,John
这个家族最早的祖先,他有两个子女Robert
和Nancy
,Robert
有两个子女Frank
和Andrew
,Nancy
只有一个子女David
。
在实验中,研究人员还收集了家庭文件,并提取了家谱中有关两个人关系的陈述语句。下面为家谱中关系的陈述语句实例:
John is the parent of Robert
Robert is a sibling of Nancy
David is a descendant of Robert
研究人员需要判断每个陈述语句是真还是假,请编写程序帮助研究人员判断。
输入格式:
输入首先给出2个正整数N(2)和M(≤),其中N为家谱中名字的数量,M为家谱中陈述语句的数量,输入的每行不超过70个字符。
名字的字符串由不超过10个英文字母组成。在家谱中的第一行给出的名字前没有缩进空格。家谱中的其他名字至少缩进2个空格,即他们是家谱中最早祖先(第一行给出的名字)的后代,且如果家谱中一个名字前缩进k个空格,则下一行中名字至多缩进k+2个空格。
在一个家谱中同样的名字不会出现两次,且家谱中没有出现的名字不会出现在陈述语句中。每句陈述语句格式如下,其中X
和Y
为家谱中的不同名字:
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
输出格式:
对于测试用例中的每句陈述语句,在一行中输出True
,如果陈述为真,或False
,如果陈述为假。
输入样例:
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
输出样例:
True True True False False
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<string.h> 4 5 struct Node 6 { 7 char name[15]; 8 char father[15]; 9 int num; //空格数 10 } people[102]; 11 12 int main() 13 { 14 int n,m; 15 char temp[75]; 16 int i,j,k; 17 scanf("%d %d",&n,&m); 18 getchar(); 19 20 for( i=0; i<n; i++) 21 { 22 people[i].num = 0; //空格数初始化为0 23 gets(temp); 24 int L = strlen(temp); 25 for( j=0; j<L; j++) 26 { 27 if( temp[j]==' ') 28 people[i].num++; 29 else 30 { 31 strcpy( people[i].name, temp+j); //复制空格以后的字符 32 break; 33 } 34 } 35 36 if( !people[i].num ) 37 strcpy( people[i].father,"root"); //如果空格数为0则表示根 38 else 39 { 40 for( k=i-1; k>=0; k--) 41 { 42 if( people[i].num> people[k].num) 43 { 44 //从后往前寻找父节点 45 strcpy( people[i].father,people[k].name); 46 break; 47 } 48 } 49 } 50 } 51 52 char a[15],b[15],c[15],d[15]; 53 char temp1[15],temp2[15]; 54 for( i=0; i<m; i++) 55 { 56 scanf("%s %s %s %s %s %s",a,d,d,b,d,c); 57 if( b[0] == 'c') 58 { 59 //X is a child of Y 60 for( k=0; k<n; k++) 61 { 62 if( !strcmp( people[k].name,a)) 63 { 64 if( !strcmp( people[k].father,c)) 65 printf("True\n"); 66 else printf("False\n"); 67 break; 68 } 69 } 70 } 71 72 else if( b[0] == 'p') 73 { 74 //X is the parent of Y 75 for( k=0; k<n; k++) 76 { 77 if( !strcmp( people[k].name,c)) 78 { 79 if( !strcmp( people[k].father,a)) 80 printf("True\n"); 81 else printf("False\n"); 82 break; 83 } 84 } 85 } 86 else if( b[0] == 's') 87 { 88 // X is a sibling of Y 89 for( k=0; k<n; k++) 90 { 91 //寻找两个结点的父节点 92 if( !strcmp( people[k].name,a)) 93 strcpy(temp1,people[k].father); 94 if( !strcmp( people[k].name,c)) 95 strcpy(temp2,people[k].father); 96 } 97 if( !strcmp(temp1,temp2)) printf("True\n"); 98 else printf("False\n"); 99 } 100 else if( b[0] == 'd') 101 { 102 //X is a descendant of Y 103 for( k=0; k<n; k++) 104 { 105 if( !strcmp( people[k].name,a)) 106 107 strcpy(temp1,people[k].father); 108 } 109 while( strcmp(temp1,c) && strcmp( temp1,"root")) 110 { 111 for( k=0; k<n; k++) 112 if( !strcmp(people[k].name,temp1)) 113 strcpy( temp1,people[k].father); 114 115 } 116 if( !strcmp(temp1,"root")) 117 printf("False\n"); 118 else printf("True\n"); 119 } 120 else if( b[0] == 'a') 121 { 122 //X is an ancestor of Y 123 for( k=0; k<n; k++) 124 { 125 if( !strcmp( people[k].name,c)) 126 127 strcpy(temp1,people[k].father); 128 } 129 while( strcmp(temp1,a) && strcmp( temp1,"root")) 130 { 131 for( k=0; k<n; k++) 132 if( !strcmp(people[k].name,temp1)) 133 strcpy( temp1,people[k].father); 134 135 } 136 if( !strcmp(temp1,"root")) 137 printf("False\n"); 138 else printf("True\n"); 139 } 140 } 141 getchar(); 142 return 0; 143 }
在这里getchar()的作用是消除 scanf输入缓冲的换行符