题意
- 给定家族树(结点总数、非叶节点总数和上下层对应关系),求每层的叶节点数。
注意
- 输入数据后从根节点递归得到每个节点的层次。(因为某些测试用例不是严格按照树层次输入的,不这样搞会挂掉一些测试点)
- 4月10日更新:这道题很简单,可以用
bfs
也可以用dfs
来遍历家族树,从而确定每个结点层次。 - 使用
dfs
的话需要注意在每个父节点的函数里给它的子节点赋值(特殊地,根节点的层次值在最外面调用dfs
之前赋予),因为当前节点的层次值需要用到其父节点的层次值,所以不好在当前结点函数里给自己赋值,那样还得多传一个参数。可以对比里面dfs
的写法,体会在当前结点处理自己还是处理子节点。
单词
- pedigree 血统,家谱
- hierarchy 层次
- fix 固定
代码
#include #include #include using namespace std;const int MAX = 100;int n, m;struct P{ //int ID; //1~99 由数组下标代替了 int K; //孩子数目 int child[MAX]; int H; //层次(连续) 0~};P p[MAX];void count(){ int a[MAX] = { 0 }; int max_H = -1; for (int i = 1; i <= n; i++) { if (p[i].K == 0) a[p[i].H]++; // 17.2.10 max_H = max(max_H, p[i].H); // max函数在algorithm头文件中 } for (int i = 0; i <= max_H; i++) { if (i == max_H) printf("%d", a[i]); else printf("%d ", a[i]); }}void dfs(int root){ if (p[root].K == 0) return; for (int i = 0; i < p[root].K; i++) { p[p[root].child[i]].H = p[root].H + 1; //这两句顺序不能颠倒,否则回溯的时候赋值:倒数第一层=倒数第二层(0)+1 dfs(p[root].child[i]); }}void bfs(int root){ queue q; q.push(root); p[root].H = 0; for (; !q.empty();) { int x = q.front(); q.pop(); for (int i = 0; i < p[x].K; i++) { p[p[x].child[i]].H = p[x].H + 1; q.push(p[x].child[i]); } }}int main(){ scanf("%d%d", &n, &m); for (int i = 1; i <= n; i++) p[i].K = 0; int pp; for (int i = 0; i < m; i++) { scanf("%d", &pp); scanf("%d", &p[pp].K); for (int j = 0; j < p[pp].K; j++) scanf("%d", &p[pp].child[j]); } p[1].H = 0; dfs(1); //bfs(1); bfs和dfs任选其一 count(); return 0;}