PAT链接:https://www.patest.cn/contests/pat-a-practise/1004
牛客网链接:https://www.nowcoder.com/pat/1/problem/4000
题意:给定一个n叉树中结点以及其孩子结点的情况,依次输出每层结点拥有的终端孩子结点个数
分析:容易想到用层次遍历
来求,结点出队列时,统计下一层结点的叶子数和非叶子数,这些非叶子结点入队,用于下一轮遍历
代码:
//写得太慢。。。
#include <iostream>
#include <queue>
#include <vector>
#include <cstring>
using namespace std;
const int N = 105;
vector<int> f[N];
int n, m;
int Cal(char *s, int len) {
int ans = 0;
for (int i = 0; i < len; i++) {
ans = ans * 10 + s[i] - '0';
}
return ans;
}
void Read() {
cin >> n >> m;
char s[3];
int node, child_num, child;
for (int i = 0; i < m; i++) {
cin >> s;
node = Cal(s,strlen(s)); //不能将长度固定为2,因为牛客网上结点小于10的有的不是2位数字表示,坑!
cin >> child_num;
for (int j = 0; j < child_num; j++) {
cin >> s;
child = Cal(s,strlen(s));
//cout << "child:" << child << '\n';
f[node].push_back(child);
}
}
//cout << f[2].size() << '\n'; (0)
}
void CountLeaves() {
int front_leaf_num, next_leaf_num;
int front_node_num, next_node_num;
int root = 1;
int level = 0;
//levelOrder
queue<int> iq;
iq.push(root);
front_node_num = 1;
front_leaf_num = f[root].size() ? 0 : 1;
//front_node_num = front_leaf_num^1;
next_leaf_num = next_node_num = 0;
while (true) {
int node = iq.front();
iq.pop(); //放在下面判空语句之前
for (vector<int>::iterator it = f[node].begin(); it != f[node].end(); it++) {
if (f[*it].size()) {
iq.push(*it);
next_node_num++; //统计下一轮待遍历结点个数
}
else next_leaf_num++; //下层终端结点数
//cout << "next_leaf_num:" << next_leaf_num << '\n';
}
if (--front_node_num == 0) {
if (level) cout << ' ';
cout << front_leaf_num;
if (!iq.empty()) {
front_leaf_num = next_leaf_num; //更新当前终端叶子结点
front_node_num = next_node_num; //更新当前待遍历结点数
next_leaf_num = next_node_num = 0;
level++;
}
else {
//作大于0的判断是排除只有一个根结点的情形
if (next_leaf_num) cout << ' ' << next_leaf_num;
break;
}
}
}
cout << '\n';
}
int main() {
Read();
CountLeaves();
return 0;
}