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