2018天梯赛第二次选拔赛

7-1 计算物体自由下落的距离(5 分)

一个物体从100米的高空自由落下。编写程序,求它在前3秒内下落的垂直距离。设重力加速度为10米/秒2​​。

输入格式:

本题目没有输入。

输出格式:

按照下列格式输出

height = 垂直距离值

结果保留2位小数。

H=1/2*g*t2

1 #include<bits/stdc++.h>
2 using namespace std;
3 int main()
4 {
5     printf("height = 45.00");
6     return 0;
7 }

7-2 有理数比较(10 分)

本题要求编写程序,比较两个有理数的大小。

输入格式:

输入在一行中按照“a1/b1 a2/b2”的格式给出两个分数形式的有理数,其中分子和分母全是整形范围内的正整数。

输出格式:

在一行中按照“a1/b1 关系符 a2/b2”的格式输出两个有理数的关系。其中“>”表示“大于”,“<”表示“小于”,“=”表示“等于”。

输入样例1:

1/2 3/4

输出样例1:

1/2 < 3/4

输入样例2:

6/8 3/4

输出样例2:

6/8 = 3/4
#include<bits/stdc++.h>
using namespace std;
int main()
{
    double a,b,c,d;
    scanf("%lf/%lf %lf/%lf",&a,&b,&c,&d);
    printf("%.0f/%.0f",a,b);
    if(a/b<c/d)printf(" < ");
    else if(a/b>c/d)printf(" > ");
    else printf(" = ");
    printf("%.0f/%.0f",c,d);
    return 0;
}

7-3 宇宙无敌大招呼(5 分)

据说所有程序员学习的第一个程序都是在屏幕上输出一句“Hello World”,跟这个世界打个招呼。作为天梯赛中的程序员,你写的程序得高级一点,要能跟任意指定的星球打招呼。

输入格式:

输入在第一行给出一个星球的名字S,是一个由不超过7个英文字母组成的单词,以回车结束。

输出格式:

在一行中输出Hello S,跟输入的S星球打个招呼。

输入样例:

Mars

输出样例:

Hello Mars
1 #include<bits/stdc++.h>
2 using namespace std;
3 int main()
4 {
5     string s;
6     cin>>s;
7     cout<<"Hello "<<s;
8     return 0;
9 }

7-4 字符串替换(15 分)

本题要求编写程序,将给定字符串中的大写英文字母按以下对应规则替换:

原字母对应字母
A Z
B Y
C X
D W
X C
Y B
Z A

输入格式:

输入在一行中给出一个不超过80个字符、并以回车结束的字符串。

输出格式:

输出在一行中给出替换完成后的字符串。

输入样例:

Only the 11 CAPItaL LeTtERS are replaced.

输出样例:

Lnly the 11 XZKRtaO OeGtVIH are replaced.
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int main()
 4 {
 5     string a,s="ZYXWVUTSRQPONMLKJIHGFEDCBA";
 6     getline(cin,a);
 7     for(int i=0;a[i];i++)
 8         if(a[i]>='A'&&a[i]<='Z')
 9             printf("%c",s[a[i]-'A']);
10         else
11             printf("%c",a[i]);
12     return 0;
13 }

7-5 点赞(20 分)

微博上有个“点赞”功能,你可以为你喜欢的博文点个赞表示支持。每篇博文都有一些刻画其特性的标签,而你点赞的博文的类型,也间接刻画了你的特性。本题就要求你写个程序,通过统计一个人点赞的纪录,分析这个人的特性。

输入格式:

输入在第一行给出一个正整数N(1000),是该用户点赞的博文数量。随后N行,每行给出一篇被其点赞的博文的特性描述,格式为"K F1 F2 .....Fk",其中1K10,Fi(i=1,....,K)是特性标签的编号,我们将所有特性标签从1到1000编号。数字间以空格分隔。

输出格式:

统计所有被点赞的博文中最常出现的那个特性标签,在一行中输出它的编号和出现次数,数字间隔1个空格。如果有并列,则输出编号最大的那个。

输入样例:

4
3 889 233 2
5 100 3 233 2 73
4 3 73 889 2
2 233 123

输出样例:

233 3
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int main()
 4 {
 5     int a,n,k,maxx=0,c;
 6     map<int,int> ma;
 7     cin>>n;
 8     for(int i=0;i<n;i++)
 9     {
10         cin>>k;
11         for(int j=0;j<k;j++)
12         {
13             cin>>a;
14             ma[a]++;
15             if(ma[a]>maxx||ma[a]==maxx&&a>c)
16             {
17                 maxx=ma[a];
18                 c=a;
19             }
20         }
21     }
22     cout<<c<<' '<<maxx;
23     return 0;
24 }

7-6 比较大小(10 分)

本题要求将输入的任意3个整数从小到大输出。

输入格式:

输入在一行中给出3个整数,其间以空格分隔。

输出格式:

在一行中将3个整数从小到大输出,其间以“->”相连。

输入样例:

4 2 8

输出样例:

2->4->8
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int main()
 4 {
 5     int a[5];
 6     cin>>a[0]>>a[1]>>a[2];
 7     sort(a,a+3);
 8     printf("%d->%d->%d",a[0],a[1],a[2]);
 9     return 0;
10 }

7-7 求e的近似值(15 分)

自然常数e可以用级数1+1/1!+1/2!++1/n!来近似计算。本题要求对给定的非负整数n,求该级数的前n项和。

输入格式:

输入第一行中给出非负整数n(1000)。

输出格式:

在一行中输出部分和的值,保留小数点后八位。

输入样例:

10

输出样例:

2.71828180

其实先暴力输出一下看看,后面都不变了

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int main()
 4 {
 5     int n;
 6     cin>>n;
 7     double a=1,b=1;
 8     for(int i=1;i<=n&&i<=11;i++)
 9     {
10         b*=i;
11         a+=1/b;
12     }
13     printf("%.8f",a);
14     return 0;
15 }

7-8 数组循环左移(20 分)

本题要求实现一个对数组进行循环左移的简单函数:一个数组a中存有n(>0)个整数,在不允许使用另外数组的前提下,将每个整数循环向左移m(≥0)个整数,在不允许使用另外数组的前提下,将每个整数循环向左移m(≥0)个位置,即将a中的数据由(a0a1a2...an-1)变换为(am....an-1a0a1....am-1)(最前面的m个数循环移至最后面的m个位置)。如果还需要考虑程序移动数据的次数尽量少,要如何设计移动的方法?

输入格式:

输入第1行给出正整数n(≤100)和整数m(≥0);第2行给出n个整数,其间以空格分隔。

输出格式:

在一行中输出循环左移m位以后的整数序列,之间用空格分隔,序列结尾不能有多余空格。

输入样例:

8 3
1 2 3 4 5 6 7 8

输出样例:

4 5 6 7 8 1 2 3

模拟一下,找找规律

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int main()
 4 {
 5     int n,m,a[105];
 6     vector<int> v;
 7     cin>>n>>m;
 8     for(int i=0;i<n;i++)
 9         cin>>a[i];
10     int p=m%n;
11     for(int i=p;i<n;i++)
12         v.push_back(a[i]);
13     for(int i=0;i<p;i++)
14         v.push_back(a[i]);
15     for(int i=0;i<n;i++)
16         printf("%d%c",v[i],i==n-1?'
':' ');
17     return 0;
18 }

7-9 列出连通集(25 分)

给定一个有N个顶点和E条边的无向图,请用DFS和BFS分别列出其所有的连通集。假设顶点从0到N1编号。进行搜索时,假设我们总是从编号最小的顶点出发,按编号递增的顺序访问邻接点。

输入格式:

输入第1行给出2个整数N(0<N≤10)E,分别是图的顶点数和边数。随后E行,每行给出一条边的两个端点。每行中的数字之间用1空格分隔。

输出格式:

按照"{v1v2v3.....vk}"的格式,每行输出一个连通集。先输出DFS的结果,再输出BFS的结果。

输入样例:

8 6
0 7
0 1
2 0
4 1
2 4
3 5

输出样例:

{ 0 1 4 2 7 }
{ 3 5 }
{ 6 }
{ 0 1 2 7 4 }
{ 3 5 }
{ 6 }

深搜DFS,广搜DFS基本操作

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int Vis[20],G[20][20],n,m;
 4 void dfs(int u)
 5 {
 6     printf(" %d",u);
 7     for(int i=0;i<n;i++)
 8     {
 9         if(!Vis[i]&&G[u][i])
10         {
11             Vis[i]=1;
12             dfs(i);
13         }
14     }
15 }
16 void bfs(int s)
17 {
18     queue<int> Q;
19     Q.push(s);
20     while(!Q.empty())
21     {
22         int u=Q.front();Q.pop();
23         printf(" %d",u);
24         for(int i=0;i<n;i++)
25         {
26             if(!Vis[i]&&G[u][i])
27             {
28                 Vis[i]=1;
29                 Q.push(i);
30             }
31         }
32     }
33 }
34 int main()
35 {
36     int u,v;
37     cin>>n>>m;
38     for(int i=0;i<m;i++)
39     {
40         cin>>u>>v;
41         G[u][v]=G[v][u]=1;
42     }
43     memset(Vis,0,sizeof(Vis));
44     for(int i=0;i<n;i++)
45     {
46         if(!Vis[i])
47         {
48             Vis[i]=1;
49             printf("{");
50             dfs(i);
51             printf(" }
");
52         }
53     }
54     memset(Vis,0,sizeof(Vis));
55     for(int i=0;i<n;i++)
56     {
57         if(!Vis[i])
58         {
59             Vis[i]=1;
60             printf("{");
61             bfs(i);
62             printf(" }
");
63         }
64     }
65     return 0;
66 }

7-10 文件传输(25 分)

当两台计算机双向连通的时候,文件是可以在两台机器间传输的。给定一套计算机网络,请你判断任意两台指定的计算机之间能否传输文件?

输入格式:

首先在第一行给出网络中计算机的总数 N (2N104​​),于是我们假设这些计算机从 1 到 N 编号。随后每行输入按以下格式给出:

I c1 c2

其中I表示在计算机c1c2之间加入连线,使它们连通;或者是

C c1 c2

其中C表示查询计算机c1c2之间能否传输文件;又或者是

S

这里S表示输入终止。

输出格式:

对每个C开头的查询,如果c1c2之间可以传输文件,就在一行中输出"yes",否则输出"no"。当读到终止符时,在一行中输出"The network is connected."如果网络中所有计算机之间都能传输文件;或者输出"There are k components.",其中k是网络中连通集的个数。

输入样例 1:

5
C 3 2
I 3 2
C 1 5
I 4 5
I 2 4
C 3 5
S

输出样例 1:

no
no
yes
There are 2 components.

输入样例 2:

5
C 3 2
I 3 2
C 1 5
I 4 5
I 2 4
C 3 5
I 1 3
C 1 5
S

输出样例 2:

no
no
yes
yes
The network is connected.

并查集基本操作

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N=1e4+5;
 4 int F[N];
 5 int Find(int x)
 6 {
 7     return F[x]==x?x:F[x]=Find(F[x]);
 8 }
 9 void Join(int a,int b)
10 {
11     int fx=Find(a);
12     int fy=Find(b);
13     if(fx!=fy)
14         F[fx]=fy;
15 }
16 void init(int n)
17 {
18     for(int i=1;i<=n;i++)F[i]=i;
19 }
20 int main()
21 {
22     int n,u,v;
23     string s;
24     cin>>n;
25     init(n);
26     while(1)
27     {
28         cin>>s;
29         if(s=="S")break;
30         cin>>u>>v;
31         if(s=="I")Join(u,v);
32         else
33         {
34             if(Find(u)==Find(v))cout<<"yes
";
35             else cout<<"no
";
36         }
37     }
38     int cnt=0;
39     for(int i=1;i<=n;i++)
40         if(F[i]==i)
41             cnt++;
42     if(cnt==1)printf("The network is connected.
");
43     else printf("There are %d components.
",cnt);
44     return 0;
45 }

7-11 重排链表(25 分)

给定一个单链表 L1→L2→...→Ln-1→Ln,请编写程序将链表重新排列为 Ln→L1→Ln-1→L2→...。例如:给定L为1→2→3→4→5→6,则输出应该为6→1→5→2→4→3。

输入格式:

每个输入包含1个测试用例。每个测试用例第1行给出第1个结点的地址和结点总个数,即正整数N(≤105)。结点的地址是5位非负整数,NULL地址用1表示。

接下来有N行,每行格式为:

Address Data Next

其中Address是结点地址;Data是该结点保存的数据,为不超过105​​的正整数;Next是下一结点的地址。题目保证给出的链表上至少有两个结点。

输出格式:

对每个测试用例,顺序输出重排后的结果链表,其上每个结点占一行,格式与输入相同。

输入样例:

00100 6
00000 4 99999
00100 1 12309
68237 6 -1
33218 3 00000
99999 5 68237
12309 2 33218

输出样例:

68237 6 00100
00100 1 99999
99999 5 12309
12309 2 00000
00000 4 33218
33218 3 -1

这个题一直22分,后来发现有多余结点的情况,结点<=k,如果循环0-k的话就超时了,详细看代码

给个样例

1 3

1 0 2

2 0 -1

3 0 4

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N=100000+5;
 4 struct Node
 5 {
 6     int u,next,w;
 7 }A[N];
 8 vector<Node> v;
 9 int main()
10 {
11     int s,k,u,next,w;
12     cin>>s>>k;
13     for(int i=0;i<k;i++)
14     {
15         cin>>u>>w>>next;
16         A[u].u=u;
17         A[u].next=next;
18         A[u].w=w;
19     }
20     int cnt=0;//所有有效的结点数<=k(可能有无效结点)
21     //for(int i=0;i<k;i++)这样写就过不去了
22     while(1)
23     {
24         v.push_back(A[s]);
25         cnt++;
26         s=A[s].next;
27         if(s==-1)break;
28     }
29     int i=0,j=cnt-1;
30     while(1)
31     {
32         //输出最后1个和第1个
33         printf("%05d %d %05d
",v[j].u,v[j].w,v[i].u);
34         printf("%05d %d ",v[i].u,v[i].w);
35         i++;j--;
36         if(i!=j)
37         {
38             if(i<cnt/2)
39                 printf("%05d
",v[j].u);
40             else//偶数结点的最后输出
41             {
42                 printf("-1
");
43                 break;
44             }
45         }
46         else//奇数结点的最后输出
47         {
48             printf("%05d
%05d %d -1
",v[j].u,v[j].u,v[j].w);
49             break;
50         }
51     }
52     return 0;
53 }

7-12 人以群分(25 分)

社交网络中我们给每个人定义了一个“活跃度”,现希望根据这个指标把人群分为两大类,即外向型(outgoing,即活跃度高的)和内向型(introverted,即活跃度低的)。要求两类人群的规模尽可能接近,而他们的总活跃度差距尽可能拉开。

输入格式:

输入第一行给出一个正整数N(2≤N≤105。随后一行给出N个正整数,分别是每个人的活跃度,其间以空格分隔。题目保证这些数字以及它们的和都不会超过231

输出格式:

按下列格式输出:

Outgoing #: N1
Introverted #: N2
Diff = N3

其中N1是外向型人的个数;N2是内向型人的个数;N3是两群人总活跃度之差的绝对值。

输入样例1:

10
23 8 10 99 46 2333 46 1 666 555

输出样例1:

Outgoing #: 5
Introverted #: 5
Diff = 3611

输入样例2:

13
110 79 218 69 3721 100 29 135 2 6 13 5188 85

输出样例2:

Outgoing #: 7
Introverted #: 6
Diff = 9359
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int main()
 4 {
 5     int n,n1=0,n2=0,a[100005];
 6     scanf("%d",&n);
 7     for(int i=0;i<n;i++)
 8         scanf("%d",&a[i]);
 9     sort(a,a+n);
10     printf("Outgoing #: %d
",n%2==0?n/2:n/2+1);
11     printf("Introverted #: %d
",n/2);
12     for(int i=0;i<n/2;i++)
13         n1+=a[i];
14     for(int i=n/2;i<n;i++)
15         n2+=a[i];
16     printf("Diff = %d
",n2-n1);
17     return 0;
18 }

7-13 关键活动(30 分)

假定一个工程项目由一组子任务构成,子任务之间有的可以并行执行,有的必须在完成了其它一些子任务后才能执行。“任务调度”包括一组子任务、以及每个子任务可以执行所依赖的子任务集。

比如完成一个专业的所有课程学习和毕业设计可以看成一个本科生要完成的一项工程,各门课程可以看成是子任务。有些课程可以同时开设,比如英语和C程序设计,它们没有必须先修哪门的约束;有些课程则不可以同时开设,因为它们有先后的依赖关系,比如C程序设计和数据结构两门课,必须先学习前者。

但是需要注意的是,对一组子任务,并不是任意的任务调度都是一个可行的方案。比如方案中存在“子任务A依赖于子任务B,子任务B依赖于子任务C,子任务C又依赖于子任务A”,那么这三个任务哪个都不能先执行,这就是一个不可行的方案。

任务调度问题中,如果还给出了完成每个子任务需要的时间,则我们可以算出完成整个工程需要的最短时间。在这些子任务中,有些任务即使推迟几天完成,也不会影响全局的工期;但是有些任务必须准时完成,否则整个项目的工期就要因此延误,这种任务就叫“关键活动”。

请编写程序判定一个给定的工程项目的任务调度是否可行;如果该调度方案可行,则计算完成整个工程项目需要的最短时间,并输出所有的关键活动。

输入格式:

输入第1行给出两个正整数N(100)和M,其中N是任务交接点(即衔接相互依赖的两个子任务的节点,例如:若任务2要在任务1完成后才开始,则两任务之间必有一个交接点)的数量。交接点按1~N编号,M是子任务的数量,依次编号为1~M。随后M行,每行给出了3个正整数,分别是该任务开始和完成涉及的交接点编号以及该任务所需的时间,整数间用空格分隔。

输出格式:

如果任务调度不可行,则输出0;否则第1行输出完成整个工程项目需要的时间,第2行开始输出所有关键活动,每个关键活动占一行,按格式“V->W”输出,其中V和W为该任务开始和完成涉及的交接点编号。关键活动输出的顺序规则是:任务开始的交接点编号小者优先,起点编号相同时,与输入时任务的顺序相反。

输入样例:

7 8
1 2 4
1 3 3
2 4 5
3 4 3
4 5 1
4 6 6
5 7 5
6 7 2

输出样例:

17
1->2
2->4
4->6
6->7

题目好长看了半天没理解意思,猜个0得了5分,看输出像是拓扑排序题,没时间就没写了

7-14 词频统计(30 分)

请编写程序,对一段英文文本,统计其中所有不同单词的个数,以及词频最大的前10%的单词。

所谓“单词”,是指由不超过80个单词字符组成的连续字符串,但长度超过15的单词将只截取保留前15个单词字符。而合法的“单词字符”为大小写字母、数字和下划线,其它字符均认为是单词分隔符。

输入格式:

输入给出一段非空文本,最后以符号#结尾。输入保证存在至少10个不同的单词。

输出格式:

在第一行中输出文本中所有不同单词的个数。注意“单词”不区分英文大小写,例如“PAT”和“pat”被认为是同一个单词。

随后按照词频递减的顺序,按照词频:单词的格式输出词频最大的前10%的单词。若有并列,则按递增字典序输出。

输入样例:

This is a test.

The word "this" is the word with the highest frequency.

Longlonglonglongword should be cut off, so is considered as the same as longlonglonglonee.  But this_8 is different than this, and this, and this...#
this line should be ignored.

输出样例:(注意:虽然单词the也出现了4次,但因为我们只要输出前10%(即23个单词中的前2个)单词,而按照字母序,the排第3位,所以不输出。)

23
5:this
4:is

感谢武汉理工大学的郭小兵老师修正测试数据!

模拟题,一次读入1个字母判断,最后放入vector里排序即可

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define psi pair<string,int>
 4 bool cmp(psi a,psi b)
 5 {
 6     return a.second>b.second||a.second==b.second&&a.first<b.first;
 7 }
 8 int main()
 9 {
10     char ch;
11     string s;
12     map<string,int> ma;
13     for(;;)
14     {
15         ch=getchar();
16         if((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')||(ch>='0'&&ch<='9')||(ch=='_'))
17         {
18             if(s.size()<=14)
19             {
20                 if(ch>='A'&&ch<='Z')
21                     ch+=32;
22                 s+=ch;
23             }
24         }
25         else
26         {
27             if(s.size()>0)
28                 ma[s]++;
29             s.clear();
30         }
31         if(ch=='#')break;
32     }
33     vector<psi> v(ma.begin(),ma.end());
34     sort(v.begin(),v.end(),cmp);
35     cout<<v.size()<<endl;
36     int cnt=(int)(ma.size()*0.1);
37     for(int i=0;i<cnt;i++)
38         cout<<v[i].second<<':'<<v[i].first<<endl;
39     return 0;
40 }

7-15 二叉搜索树的结构(30 分)

二叉搜索树或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;它的左、右子树也分别为二叉搜索树。(摘自百度百科)

给定一系列互不相等的整数,将它们顺次插入一棵初始为空的二叉搜索树,然后对结果树的结构进行描述。你需要能判断给定的描述是否正确。例如将{ 2 4 1 3 0 }插入后,得到一棵二叉搜索树,则陈述句如“2是树的根”、“1和4是兄弟结点”、“3和0在同一层上”(指自顶向下的深度相同)、“2是4的双亲结点”、“3是4的左孩子”都是正确的;而“4是2的左孩子”、“1和3是兄弟结点”都是不正确的。

输入格式:

输入在第一行给出一个正整数N(≤100),随后一行给出N个互不相同的整数,数字间以空格分隔,要求将之顺次插入一棵初始为空的二叉搜索树。之后给出一个正整数M(≤100),随后M行,每行给出一句待判断的陈述句。陈述句有以下6种:

  • A and B are siblings,即"AB是兄弟结点";
  • A is the parent of B,即"AB的双亲结点";
  • A is the left child of B,即"AB的左孩子";
  • A is the right child of B,即"AB的右孩子";
  • A and B are on the same level,即"AB在同一层上"。

题目保证所有给定的整数都在整型范围内。

输出格式:

对每句陈述,如果正确则输出Yes,否则输出No,每句占一行。

输入样例:

5
2 4 1 3 0
8
2 is the root
1 and 4 are siblings
3 and 0 are on the same level
2 is the parent of 4
3 is the left child of 4
1 is the right child of 2
4 and 0 are on the same level
100 is the right child of 3

输出样例:

Yes
Yes
Yes
Yes
Yes
No
No
No

一个二叉搜索树题,得用链表,开数组内存吃不消,最大100层

建完树,6种情况判断一下即可,思路很清晰,注意仔细,详细看代码

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 struct Node
  4 {
  5     int data;
  6     Node *Left,*Right;
  7     Node():data(-1),Left(NULL),Right(NULL){}
  8 };
  9 Node *addnode(){return new Node();}//开结点
 10 Node *root,*FI;
 11 int flag;//用来标记是否继续递归,1表示找到
 12 void Create(Node *u,int a)//建立二叉搜索树
 13 {
 14     if(u->data==-1)
 15     {
 16         u->data=a;
 17         return ;
 18     }
 19     else
 20     {
 21         if(a>u->data)
 22         {
 23             if(u->Right==NULL)
 24                 u->Right=addnode();
 25             Create(u->Right,a);
 26         }
 27         else
 28         {
 29             if(u->Left==NULL)
 30                 u->Left=addnode();
 31             Create(u->Left,a);
 32         }
 33     }
 34 }
 35 void Find(Node *u,int a)
 36 {
 37     if(u->data==a)
 38     {
 39         flag=1;
 40         FI=u;
 41         return;
 42     }
 43     if(flag==0)
 44     {
 45         if(u->Left!=NULL)
 46             Find(u->Left,a);
 47         if(u->Right!=NULL)
 48             Find(u->Right,a);
 49     }
 50 }
 51 void FFF(Node *u,int a,int b)
 52 {
 53     if(u->Left!=NULL&&u->Right!=NULL)
 54     {
 55         if(u->Left->data==a&&u->Right->data==b)flag=1;
 56         if(u->Right->data==a&&u->Left->data==b)flag=1;
 57     }
 58     if(flag==0)
 59     {
 60         if(u->Left!=NULL)
 61             FFF(u->Left,a,b);
 62         if(u->Right!=NULL)
 63             FFF(u->Right,a,b);
 64     }
 65 }
 66 void Level(Node *u,int a,int k)
 67 {
 68     if(u->data==a)
 69     {
 70         flag=k;
 71         return;
 72     }
 73     if(flag==0)
 74     {
 75         if(u->Left!=NULL)
 76             Level(u->Left,a,k+1);
 77         if(u->Right!=NULL)
 78             Level(u->Right,a,k+1);
 79     }
 80 }
 81 int main()
 82 {
 83     root=addnode();
 84     int n,m,A,B,a;
 85     cin>>n;
 86     for(int i=0;i<n;i++)
 87     {
 88         cin>>a;
 89         Create(root,a);
 90     }
 91     cin>>m;
 92     string s;
 93     for(int i=0;i<m;i++)
 94     {
 95         int f=0;
 96         cin>>A>>s;
 97         if(s=="is")
 98         {
 99             cin>>s>>s;
100             if(s=="root")//1.A是树的根
101             {
102                 if(root->data==A)
103                     f=1;
104             }
105             else if(s=="parent")//3.A是B的父母
106             {
107                 cin>>s>>B;
108                 flag=0;
109                 FI=NULL;
110                 Find(root,A);
111                 Node *u=FI;
112                 if(u!=NULL)//A存在
113                 {
114                     //A左右儿子存在且==B
115                     if(u->Left!=NULL&&u->Left->data==B)f=1;
116                     if(u->Right!=NULL&&u->Right->data==B)f=1;
117                 }
118             }
119             else if(s=="left")//4.A是B的左孩子
120             {
121                 cin>>s>>s>>B;
122                 FI=NULL;
123                 flag=0;
124                 Find(root,B);
125                 Node *u=FI;
126                 if(u!=NULL)//B存在
127                 {
128                     //B左儿子存在且==A
129                     if(u->Left!=NULL&&u->Left->data==A)f=1;
130                 }
131             }
132             else if(s=="right")//5.A是B的右孩子
133             {
134                 cin>>s>>s>>B;
135                 flag=0;
136                 FI=NULL;
137                 Find(root,B);
138                 Node *u=FI;
139                 if(u!=NULL)//B存在
140                 {
141                     //B左儿子存在且==A
142                     if(u->Right!=NULL&&u->Right->data==A)f=1;
143                 }
144             }
145         }
146         else if(s=="and")
147         {
148             cin>>B>>s>>s;
149             if(s=="siblings")//2.A和B是兄弟结点
150             {
151                 flag=0;
152                 FFF(root,A,B);
153                 if(flag)f=1;
154             }
155             else//6.A和B在同一层上
156             {
157                 cin>>s>>s>>s;
158                 flag=0;
159                 Level(root,A,1);
160                 int f1=flag;
161                 flag=0;
162                 Level(root,B,1);
163                 int f2=flag;
164                 //结点存在且层数相等
165                 if(f1>0&&f2>0&&f1==f2)f=1;
166             }
167         }
168         printf("%s
",f?"Yes":"No");
169     }
170     return 0;
171 }
原文地址:https://www.cnblogs.com/taozi1115402474/p/8591971.html