1. 程式人生 > >PAT 1004 Counting Leaves

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 ;
}