PAT 1004 Counting Leaves

问题重述:

A family hierarchy is usually presented by a pedigree tree. Your job is to count those family members who have no child.
一个家族的繁衍通常用一棵家族树来表示,你的任务在于计算这其中没有孩子的家族成员的数量。

输入和输出示例:

输入:每个文件包含有一个测试样例,每个测试样例中包含有如下内容:
N: 家族树中的节点总个数
M:家族树中非叶子节点的个数

输出:每一层中叶子节点的个数

Sample Input
2 1
01 1 02
Sample Output
0 1

问题分析:

通过读题,可以较为清晰地看到数据结构与树有关,但是应当怎样构建树值得思考。在一开始,我想到了包括多叉树、左孩子右兄弟结构等等,当时学数据结构时仅存的关于树的记忆都显示出来。但是,当再次分析这道题时,你会发现,这道题考察的是一个父母节点有没有子节点,甚至连子节点的个数都不需要具体确定;也就是说,对于每一个节点而言我只需要知道一个布尔值,即有没有孩子。分析到这里,复杂的数据结构就可以被避免了。于是,我设计了下面的一个节点结构:

typedef struct Tree_Node
{
int child_num ;
int father ;
int level ;
int active ;
}Tree_Node ;

其中child_num表示对是否有孩子的判断,father是对父母节点索引的记录,level是记录该节点所在的层数,active表示该节点是否是处于激活的状态;

具体的算法为,创建节点的数组,并进行初始化。因为题目中fix了根节点的编号,因此可直接对下标为1的节点进行特殊处理。然后完成输入,在每输入一行时,对这一行涉及的节点相关信息进行更新,这其中包括:新节点的激活;新节点的父节点更新;新节点的父节点的child_num的更新;
在输入完成之后,即可以遍历该节点数组,找到每个level中child_num显示为False的节点数目,输出即可;

注意:
我基于上面的方法写出程序进行测试,始终有两个测试点无法通过。通过在网上查阅其他的博文,发现一种错误在于:题目中给定的输入可能是无序的。也就是说,父节点很有可能晚于子节点出现。这一点的重要性体现在level上,因为子节点所在的level是要根据父节点进行更新的,如果父节点的level都无法得到,那子节点也不行。因此,解决的方法在于完成输入后,通过统一的遍历,完成对于level的设定;

收获

刚刚开始刷PAT系列,还是希望提高自己的编程能力,初期的时候这些题目还要花很长的时间,当AC后回过头来看,又有种失望,觉得自己不应该在这些点上卡住很久。希望通过这个博客记录下自己的点点滴滴吧,虽然现在真的很水,但每天都要有一点点的进步。以后一定要好好审题啊!

代码

#include<stdio.h>
#include<stdlib.h>

#define MAXNUM 100
#define End -1
#define True 1
#define False 0

int M ;   // the number of the node
int N  ;  // the number of the non-leaf node

typedef struct Tree_Node
{
        int child_num ;
        int father ;
        int level ;
        int active ;
}Tree_Node ;

int main()
{
        Tree_Node TA[MAXNUM] ;
        int i , j ;
        int a;
        int c ;
        int pos ;
        int number =0 ;
        int U[MAXNUM];
        scanf("%d%d",&M,&N) ;
        TA[0].child_num = End;
        TA[0].level = End ;
        TA[0].active = False ;
        TA[0].father = False ;
        TA[1].level = 1 ;
        TA[1].active = True ;
        TA[1].child_num = End ;
        TA[1].father = End ;
        for( i = 2 ; i<MAXNUM ; i++){
                TA[i].child_num = End ;
                TA[i].level = End ;
                TA[i].active = False ;
                TA[i].father = End ;
        }
        for(i=0;i<N;i++){
                scanf("%d%d",&a,&c);
                TA[a].active=True;
                for(j=0;j<c;j++){
                        scanf("%d",&pos);
                        TA[pos].active=True;
                        TA[a].child_num = True ;
                        TA[pos].father = a ;
                }
        }
        for(i=2;i<MAXNUM;i++){
                TA[i].level = TA[TA[i].father].level+1;
        }
        for(i=0;i<MAXNUM;i++){
                U[i]=End;
                if(TA[i].level!=End&&TA[i].active==True){
                        U[TA[i].level] = 0 ;
                }
        }
        for(i=1;i<MAXNUM;i++){
                if(U[i]!=End){
                        number++;
                }
        }
        for(i=1;i<MAXNUM;i++){
                if(TA[i].active==True&&TA[i].child_num==End){
                        U[TA[i].level]++;
                }
        }
        for(i=1;i<number;i++){
                printf("%d ",U[i]);
        }
        printf("%d",U[number]);
        return 0 ;
}

猜你喜欢

转载自blog.csdn.net/ComeTender/article/details/77825323