原题目: 1004 Counting Leaves (30 分)
题意
给出结点树N以及非叶结点数M;随后:结点下标ID,孩子数K,孩子结点下标ID(下标为两位数)。
👉要求输出从根结点开始的每层的叶子结点数(感觉这句话原文不太好理解,po在下面)。
For each test case, you are supposed to count those family members who have no child for every seniority level starting from the root.
① count什么?those family members who have no child
② 为谁count?for every seniority level starting from the root
分析
- 孩子表示法: 用二维vector数组保存每个有孩子结点的结点及其孩子结点;如此一来,可 通过.size()来判断是否叶子结点。
- DFS:layer能从1开始顺序递增,以此记录每层的叶子结点数——
①另开一个数组ans——下标为层次,元素为该层次的叶结点数。
②递归边界:遇到叶结点.size()==0,增加该层叶结点数,更新树高。
③递归式:深度优先地遍历每个非叶节点的每个孩子结点,每递归一次深度+1。
【注】必要时,还是先声明好数组大小可以方便很多,如利用下标。
知识点
- 孩子表示法: 数组vector用push_back保存非叶节点的孩子结点。
- DFS思想——计算每层叶结点数。
词汇
WORDS & CHUNKS | 释义 | WORDS & CHUNKS | 释义 |
---|---|---|---|
pedigree | 家谱 | non-leaf node | 非叶节点 |
seniority level | 资历等级 |
CODE
#include <iostream>
#include <vector>
using namespace std;
int n, m;
vector<int> v[101], ans;
int height = -1; //记录树高
void DFS(int index, int layer);
int main()
{
cin >> n >> m;
// v.resize(n+1);
ans.resize(n+1);
for ( int i=0; i<m; i++ ){
int index, child; //非叶节点下标,孩子个数
cin >> index >> child;
for ( int j=0; j<child; j++ ){
int tmp; //孩子下标
cin >> tmp;
v[index].push_back(tmp); //第index行存其孩子结点
}
}
//深度遍历得各层次叶结点个数
DFS(1, 1);
//输出
for ( int i=1; i<=height; i++ ){
printf("%d%s", ans[i], i==height?"":" ");
}
return 0;
}
void DFS(int index, int layer){
if ( v[index].size()==0 ){ //叶子结点
ans[layer]++; //第layer层的叶结点个数+1
height = max(height, layer);
return;
}
for ( int i=0; i<v[index].size(); i++ ){
DFS(v[index][i], layer+1);
}
}
注意点
&1 vector用resize定义大小时,不能用push_back扩展成二维数组
必须在声明时说好大小,才能用push_back扩展成二维数组,如下
vector<int> v(100);
v[3].push_back(4);
&2 本题的结点下标问题
题目虽然举列说了ID为两位数,如 01,但不代表下标一定从 “1” 开始,有可能从 “0” 开始,即 00,这点要小心。