✍个人博客:https://blog.csdn.net/Newin2020?spm=1011.2415.3001.5343
📚专栏地址:PAT题解集合
📝原题地址:题目详情 - 1004 Counting Leaves (pintia.cn)
🔑中文翻译:数叶子结点
📣专栏定位:为想考甲级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.
Input Specification:
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:
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-digitID
’s of its children. For the sake of simplicity, let us fix the root ID to be01
.The input ends with N being 0. That case must NOT be processed.
Output Specification:
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.
The sample case represents a tree with only 2 nodes, where
01
is the root and02
is its only child. Hence on the root01
level, there is0
leaf node; and on the next level, there is1
leaf node. Then we should output0 1
in a line.Sample Input:
2 1 01 1 02
Sample Output:
0 1
题意
第一行给定一个 N N N 和 M M M ,分别表示该树的结点总数量以及非叶子结点数量。
接下来的 M M M 行,输入每个非叶子结点的孩子结点,格式为:
ID K ID[1] ID[2] ... ID[K]
ID
表示非叶子结点的编号,
K
K
K 表示该结点有
K
K
K 个孩子结点,然后紧跟
K
K
K 个孩子结点的编号。
让我们统计该树中每一层的叶子结点个数,并输出。
如下图所示,cnt
表示每一层的叶子结点数:
思路
- 用链式前向星的方法存储该树。
- 递归更新每层叶子结点的数量,因为题目给定根结点是
1
,所以从1
开始向下递归,去递归它的孩子结点。如果在递归过程中h[u] == -1
即结点u
没有孩子结点,则将该层的叶子节点数加1
。 - 最后输出每层的叶子结点数量。
代码
#include<bits/stdc++.h>
using namespace std;
const int N = 110;
int h[N], ne[N], e[N], idx; //邻接表
int cnt[N]; //计算每一层的叶子结点数
int max_depth; //树的最大深度
//链式前向星,往a向b加一条边
void add(int a, int b)
{
e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}
//递归更新每层的叶子结点数量
void dfs(int u, int depth)
{
//如果当前结点已经是叶子结点,则进行更新操作
if (h[u] == -1)
{
max_depth = max(max_depth, depth);
cnt[depth]++;
return;
}
//递归遍历其孩子结点
for (int i = h[u]; ~i; i = ne[i])
dfs(e[i], depth + 1);
}
int main()
{
int n, m;
cin >> n >> m;
//输入结点之间的关系
memset(h, -1, sizeof h);
while (m--)
{
int a, b, k;
cin >> a >> k;
while (k--)
{
cin >> b;
add(a, b);
}
}
dfs(1, 0); //根结点为1
//输出每层的叶子结点数
cout << cnt[0];
for (int i = 1; i <= max_depth; i++)
cout << " " << cnt[i];
cout << endl;
return 0;
}