题目链接:http://pat.zju.edu.cn/contests/pat-practise/1004
该题是个模拟类吧,个人觉得,题目要求计算出家谱树中每一层的叶节点个数,因为只是数数目,所以在做题的时候可以用一些小聪明省去不需要的内存开销和逻辑处理,比如不需要记录某一个结点有多少孩子,更不用提这些孩子都是哪些结点,只用记录一个值:该节点有没有孩子;还有就是记录该节点所在层数,自己确定根结点在第一层,然后根据输入的家谱关系更新所有结点的level值,所以树中节点的结构体为:
1 typedef struct
2 {
3 int level;//该结点所在层数
4 int haveChild;//该节点有没有孩子
5 int updated;//该节点的level更新过没
6 }node;
程序刚开始时,每个结点的level初始化为0,程序输入家谱关系时,每个结点的level值不是简单的父节点level+1,因为父节点此时level可能并没有更新,还是处于初始状态,所以,level只是记录父节点编号,然后再用一个单独的循环,更新所有结点的level,同时记录每一层的叶节点个数,这样做使整个程序的内存开销和逻辑处理简单了很多。
1 #include <stdio.h>
2 #include <stdlib.h>
3
4 typedef struct
5 {
6 int level;//该结点所在层数
7 int haveChild;//该节点有没有孩子
8 int updated;//该节点的level更新过没
9 }node;
10
11 int charToInt(char a[2])
12 {
13 int i = 0;
14 i += a[0] - '0';
15 i *= 10;
16 i += a[1] - '0';
17 return i;
18 }
19
20 int main()
21 {
22 int n, m;//n为树中所有的结点数,m为树中所有非叶结点数目,要保证最后的输出结果相加等于(n - m)
23 int k;
24 int i,j;
25 char tempid[2];
26 char input[2];
27 node family[120];//family[0]不使用,因为根节点是01
28 int father,updatenumber;
29 int leaf[120];//数出这颗树中每一层的叶子结点数,leaf[0]不使用,因为层数从1开始
30 int maxlevel;//记录leaf数组上界位置
31
32 while(scanf("%d %d", &n, &m) != EOF)
33 {
34 /*输入时每个结点的level不是简单的父节点level+1,因为很可能父节点此时还处于初始状态
35 ,所以只是存储父节点的id值,然后再一个循环一次性更新所有的level值*/
36 for(i = 1; i <= n; i ++)
37 {
38 family[i].level = 0;//所有都初始化为0
39 family[i].haveChild = 0;//都没有孩子
40 family[i].updated = 0;
41 }
42 for(i = 1; i < 120; i ++)
43 {
44 leaf[i] = 0;
45 }
46 for(i = 0; i < m; i ++)
47 {
48 scanf("\n%s %d", tempid, &k);
49 father = charToInt(tempid);
50 family[father].haveChild = 1;
51 for(j = 0; j < k; j ++)
52 {
53 scanf(" %s", input);
54 family[charToInt(input)].level = father;
55 }
56 //printf("n = %d m = %d id = %s k = %d child = %s\n", n, m, tempid, k, input);
57 }
58 family[1].level = 1;
59 family[1].updated = 1;
60 updatenumber = 1;//已经更新成功一个结点
61 if(family[1].haveChild == 0)
62 {
63 leaf[family[1].level] ++;
64 maxlevel = family[1].level;
65 }
66 else
67 {
68 maxlevel = 1;
69 while(updatenumber < n)//如果根节点都没有孩子,那么树就不需要再更新了
70 {
71 for(i = 2; i <= n; i ++)//根节点的level值不需要更新
72 {
73 if(family[i].updated)//该节点已经更新过
74 {
75 continue;
76 }
77 else
78 {
79 father = family[i].level;
80 if(family[father].updated)//父节点已经更新过
81 {
82 family[i].level = family[father].level + 1;
83 family[i].updated = 1;
84 updatenumber ++;
85 if(family[i].haveChild == 0)
86 {
87 leaf[family[i].level] ++;
88 if(maxlevel < family[i].level)
89 {
90 maxlevel = family[i].level;
91 }
92 }
93 }
94 else
95 {
96 continue;
97 }
98 }
99 }
100 }
101 }
102 for(i = 1; i <= maxlevel; i ++)
103 {
104 if(i != 1)
105 {
106 printf(" ");
107 }
108 printf("%d", leaf[i]);
109 }
110 printf("\n");
111 }
112
113 return 0;
114 }