A family hierarchy is usually presented by a pedigree tree. Your job is to count those family members who have no child.node
一個家族的等級一般是由一個系譜樹表示的。你的工做是統計那些沒有孩子的家庭成員。ios
Each input file contains one test case. Each case starts with a line containing 0<N<100, the number of nodes in a tree, and M (<N), the number of non-leaf nodes. Then M lines follow, each in the format:c++
每一個輸入文件包含一個測試用例。每一個案例都從一行開始,該行包含0 < n < 100、樹中節點的數量和 m (< n)、非葉節點的數量。而後是 m 行,每行格式以下:git
ID K ID[1] ID[2] ... ID[K]
where ID
is a two-digit number representing a given non-leaf node, K
is the number of its children, followed by a sequence of two-digit ID
's of its children. For the sake of simplicity, let us fix the root ID to be 01
.算法
其中 ID 是表示給定非葉節點的兩位數,k 是其子節點的數量,後面是其子節點的兩位數 ID 序列。爲了簡單起見,讓咱們將根 ID 修改成01。數組
The input ends with N being 0. That case must NOT be processed.測試
輸入結束時 n 爲0。這種狀況不能被處理。spa
For each test case, you are supposed to count those family members who have no child for every seniority level starting from the root. The numbers must be printed in a line, separated by a space, and there must be no extra space at the end of each line.翻譯
對於每個測試案例,你應該從根本開始計算那些沒有子女的家庭成員的資歷水平。數字必須打印在一行中,由一個空格分隔,而且在每行的末尾必須沒有額外的空格。code
The sample case represents a tree with only 2 nodes, where 01
is the root and 02
is its only child. Hence on the root 01
level, there is 0
leaf node; and on the next level, there is 1
leaf node. Then we should output 0 1
in a line.
示例案例表示一個只有2個節點的樹,其中01是根,02是它的惟一子節點。所以,在根01級上,有0個葉節點; 在下一級上,有1個葉節點。那麼咱們應該在一行中輸出01。
2 1 01 1 02
0 1
簡單地講,這道題就是在求一棵多叉樹的葉子節點的數量,並按照層的順序打印!若是沒有葉子結點就打印0,不然輸出葉子結點個數。
粗略地想想,層序遍歷和前序遍歷均可以完成,這裏用的是深度優先算法,也就是先序遍歷。
給出一個樣例的示意圖:
01
是根節點,由於它有一個子節點02
因此它不是葉子結點,而02
是葉子結點,所以最後的輸出爲:
0 1
接下來來實現程序。
// 全局變量 vector<int> nodes[100]; // 每一個元素表明一個節點鏈表 int pedigree[100]; // 族譜樹中每一層的葉子結點的數量 int pedigree_depth = -1; // 族譜樹的最大深度 int main...(省略部分) int N, M, node, num, child; // 處理第一行 cin >> N >> M; // 遍歷全部的非葉節點,構建節點鏈表 for (int i = 0; i < M; ++i) { cin >> node >> num; for (int j = 0; j < num; ++j) { cin >> child; nodes[node].push_back(child); } }
這裏用了一個vector的數組來存儲每一個節點的子節點鏈表。
/** * 深度優先算法,遍歷整個家族樹,若是找到葉子結點就加入到全局變量數組中 * @param index 下標 * @param depth 深度 */ void dfs(int index, int depth) { if (nodes[index].empty()) { // 若是這個節點沒有子節點,那麼就是葉子結點 pedigree[depth]++; // 這個葉子結點的深度若是超過本來記錄的最大深度,那麼就更新最大深度 pedigree_depth = depth > pedigree_depth ? depth : pedigree_depth; return; } // 遍歷該節點的全部子節點 for (int i : nodes[index]) { // 由於往下走了一層,因此深度加1 dfs(i, depth + 1); } }
爲了提升效率,不用每次都遍歷整個族譜葉子個數的數組,咱們可使用一個全局變量pedigree_length
來肯定整個數組的長度,提升最後的打印效率。
// 數組默認值爲0,這裏輸出這個數組的所有內容,長度爲pedigree_length cout << pedigree[0]; for (int i = 1; i <= pedigree_depth; ++i) { cout << " " << pedigree[i]; }
#include <iostream> #include <vector> using namespace std; vector<int> nodes[100]; // 每一個元素表明一個節點鏈表 int pedigree[100]; // 族譜樹中每一層的葉子結點的數量 int pedigree_depth = -1; // 族譜樹的最大深度 /** * 深度優先算法,遍歷整個家族樹,若是找到葉子結點就加入到全局變量數組中 * @param index 下標 * @param depth 深度 */ void dfs(int index, int depth) { if (nodes[index].empty()) { // 若是這個節點沒有子節點,那麼就是葉子結點 pedigree[depth]++; // 這個葉子結點的深度若是超過本來記錄的最大深度,那麼就更新最大深度 pedigree_depth = depth > pedigree_depth ? depth : pedigree_depth; return; } // 遍歷該節點的全部子節點 for (int i : nodes[index]) { // 由於往下走了一層,因此深度加1 dfs(i, depth + 1); } } int main() { int N, M, node, num, child; // 處理第一行 cin >> N >> M; // 遍歷全部的非葉節點,構建節點鏈表 for (int i = 0; i < M; ++i) { cin >> node >> num; for (int j = 0; j < num; ++j) { cin >> child; nodes[node].push_back(child); } } // 對族譜樹進行深度優先遍歷 dfs(1, 0); // 數組默認值爲0,這裏輸出這個數組的所有內容,長度爲pedigree_length cout << pedigree[0]; for (int i = 1; i <= pedigree_depth; ++i) { cout << " " << pedigree[i]; } return 0; }